目录
本文第1部分介绍了达梦数据库的3种事务隔离级别,第2部分通过测试观察不同级别之间的区别。
1.DM事务隔离级别
DM数据库支持三种事务隔离级别:读未提交、读提交和串行化。其中,读提交是DM数据库默认使用的事务隔离级别。
1.1读提交隔离级
DM 数据库的读提交隔离可以确保只访问到已提交事务修改的数据,保证数据处于一致
性状态,能够满足大多数应用的要求,并最大限度的保证系统并发性能。
用户可以在事务开始时使用以下语句设定事务为读提交隔离级:
SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
1.2读未提交隔离级
读未提交隔离级别是最不严格的隔离级别。实际上,在使用这个隔离级别时,有可能发生脏读、不可重复读和幻像。一般来说,读未提交隔离级别通常只用于访问只读表和只读视图,以消除可见性判断带来的系统开销,提升查询性能。
用户可以在事务开始时使用以下语句,设定事务为读未提交隔离级:
SQL> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
此外,DM 还允许用户在 SELECT 语句的末尾加上 WITH UR 以指定当前查询语句的隔离级为读未提交,即允许脏读,并在该语句结束时自动恢复为原来的隔离级。
1.3串行化隔离级
在要求消除不可重复读取或幻读的情况下,我们可以设置事务隔离级为串行化。
用户可以在事务开始时使用以下语句设定事务为串行化隔离级:
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
1.4隔离级别表
在 SQL-92 标准中,定义了四种隔离级别:读未提交、读提交、可重复读和串行化。每种隔离级别下对于读数据有不同的要求,下表中列出四种隔离级别下系统允许/禁止哪些类型的读数据现象。其中“Y”表示允许,“N”表示禁止。
1. 脏读(DirtyRead)
所谓脏读就是对脏数据的读取,而脏数据所指的就是未提交的已修改数据。
2. 不可重复读(Non-RepeatableRead)
一个事务先后读取同一条记录,但两次读取的数据不同,我们称之为不可重复读。如果
一个事务在读取了一条记录后,另一个事务修改了这条记录并且提交了事务,再次读取记录
时如果获取到的是修改后的数据,这就发生了不可重复读情况。
3. 幻读(PhantomRead)
一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其
查询条件的新数据,这种现象就称为幻读
2.测试
2.1读未提交隔离级
读未提交隔离级允许脏读。下面我们通过实验来观察。
1.准备测试数据
create table tb_test_uncommit (
id int,
c1 varchar(30)
);
在会话1(会话号145566328)中,插入1条数据,不执行commit
SQL> SELECT '当前会话id:'||sessid||',当前事务id:'||id FROM V$TRX t where T.SESS_ID=sessid;
SQL> insert into tb_test_uncommit values(1,'uncommit测试');
2.在新会话中测试读现象
1)新会话的ID是:139960573195272
SQL> SELECT SESSID;
2)设置读未提交隔离级
SQL> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SQL> select t.* from tb_test_uncommit t;
查询到了其他事务未提交的数据,发生了脏读现象
3)设置读提交隔离级
SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
SQL> select t.* from tb_test_uncommit t;
未发生脏读现象
4)设置串行化隔离级
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SQL> select t.* from tb_test_uncommit t;
未发生脏读现象
2.2串行化隔离级
“串行化”与默认的“读提交”隔离级的区别在于“不可重复读”和“幻读”现象。
举个例子:事务A查询表TB1中c1=1的数据有1条,且c2字段值是’aaa’,事务A未结束,此时事务B修改了TB1中c1=1的数据,将c2更新为’bbb’,事务B执行commit。之后,事务A第2次查询表TB1中c1=1的数据,这时看到c2的值仍然是’aaa’。这是因为串行化隔离级禁用了“不可重复读”。具体情况看下面的测试:
1.准备数据
create table tb1
(
c1 int,
c2 varchar(10)
);
INSERT INTO TB1 VALUES(1,'aaa');
commit;
2.设置串行化隔离级别,在事务A中查询数据
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
SQL> SELECT '当前会话id:'||sessid||',当前事务id:'||id FROM V$TRX t where T.SESS_ID=sessid;
SQL> select * from TB1 where c1=1;
3.会话B修改数据,并提交
SQL> SELECT '当前会话id:'||sessid||',当前事务id:'||id FROM V$TRX t where T.SESS_ID=sessid;
SQL> update TB1 set c2='bbb' where c1=1;
SQL> commit;
4.在事务A中第2次查询数据
SQL> SELECT '当前会话id:'||sessid||',当前事务id:'||id FROM V$TRX t where T.SESS_ID=sessid;
SQL> select * from TB1 where c1=1;
我们看到,B事务修改c2为‘bbb’后执行了commit,事务A看到的值还是'aaa',这是因为串行化隔离级禁用了“不可重复读”。
幻读现象的测试步骤同上,可以将事务B中的UPDATE改为INSERT,插入几条ID值为1的数据,观察是否有幻读现象。
本文结束!
参考文档: 《DM8系统管理员手册》
日期:20240903