隔离级别:一个事务必须与由其他事务进行的资源或数据更改相隔离的程度。
隔离级别从允许的并发副作用(例如,脏读或虚拟读取)的角度进行描述。
SQL 标准中,定义了 4 级隔离级别及事务处理语言(TPL),防止出现如下事务隔离现象:
更新异常:一个会话能将另外一个会话未提交的数据变更(增删改)覆盖掉。通常使用数据库锁机制来避免该问题。
脏读:当前会话能读取其他会话未提交事务的数据。
不可重复读:当前会话多次执行同一条查询 SQL,其他会话对满足该 SQL 条件的数据进行更新并提交,故当前会话每次读取的数据可能与前一次的值不同。
幻读:当前会话多次执行同一条查询 SQL,其他会话对满足该 SQL 条件的数据进行新增/删除并提交,故当前会话某次读取到的数据记录可能会比前次增多或减少。
达梦官方手册写的:
DM 数据库支持三种事务隔离级别:读未提交、读提交和串行化
其中,读提交是 DM 数据库默认使用的事务隔离级别。
可重复读升级为更严格的串行化隔离级。
下面我们测试下,达梦到底支持几种隔离级别?
SQL> select isolation from v$trx;
LINEID ISOLATION
---------- -----------
1 1
2 1
3 1
4 1
5 1
used time: 0.297(ms). Execute id is 1419.
--1:读提交(默认)
读未提交隔离级别是最不严格的隔离级别。实际上,在使用这个隔离级别时,有可能发生脏读、不可重复读和幻像。一般来说,读未提交隔离级别通常只用于访问只读表和只读视图,以消除可见性判断带来的系统开销,提升查询性能。
SQL> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
executed successfully
used time: 0.213(ms). Execute id is 3507.
--查看隔离级别
SQL> select isolation from v$trx;
LINEID ISOLATION
---------- -----------
5 0
--可以看到读未提交隔离级:ISOLATION=0
--会话一:执行update未提交
SQL> update yangkai1.tb1 set name='杨凯' where id=1;
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522703 1 杨凯
used time: 0.335(ms). Execute id is 3508.
会话二:查询
SQL> SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
executed successfully
used time: 0.201(ms). Execute id is 6505.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522703 1 杨凯
used time: 0.310(ms). Execute id is 6506.
结论:会话2可以查看到会话1未提交的数据
DM 数据库的读提交隔离可以确保只访问到已提交事务修改的数据,保证数据处于一致性状态,能够满足大多数应用的要求,并最大限度的保证系统并发性能,但可能会出现不可重复读取和幻像读。
--会话1
SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
executed successfully
--查看隔离级别
SQL> select isolation from v$trx;
LINEID ISOLATION
---------- -----------
5 1
--读已提交隔离级:ISOLATION=1
--会话1执行update
SQL> update yangkai1.tb1 set name='张三' where id=1;
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522792 1 张三
used time: 0.389(ms). Execute id is 6214.
--会话二
SQL> SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
executed successfully
used time: 0.214(ms). Execute id is 6413.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522703 1 杨凯
used time: 0.407(ms). Execute id is 6414.
--没有提交,看不到的
会话一
SQL>commit;
会话二:
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522792 1 张三
--结论:只有会话1提交,会话2才能看到
SQL> SET TRANSACTION ISOLATION LEVEL repeatable read ;
executed successfully
used time: 0.380(ms). Execute id is 6216.
--查看隔离级别:
SQL> SELECT isolation FROM V$TRX;
LINEID ISOLATION
---------- -----------
5 3
--可重复读离级:ISOLATION=3 --为什么是3
used time: 0.680(ms). Execute id is 6217.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522792 1 张三
used time: 0.291(ms). Execute id is 6219.
--会话一
SQL> update yangkai1.tb1 set name='王五' where id=1;
affect rows 1
used time: 0.803(ms). Execute id is 6220.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522873 1 王五
used time: 0.330(ms). Execute id is 6221.
--会话二
SQL> SET TRANSACTION ISOLATION LEVEL repeatable read ;
executed successfully
used time: 0.304(ms). Execute id is 6416.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522792 1 张三
used time: 0.340(ms). Execute id is 6417.
--会话一
SQL> commit;
executed successfully
used time: 4.174(ms). Execute id is 6222.
SQL>
--会话二
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522792 1 张三
used time: 0.332(ms). Execute id is 6418.
--此时查询到的记录和之前一致,并没有因为会话一提交了记录发生改变
在要求消除不可重复读取或幻像读的情况下,我们可以设置事务隔离级为串行化。跟读提交隔离级相比,串行化事务的查询本身不会增加任何代价,但修改数据可能引发“串行化事务被打断”错误。
具体来说,当一个串行化事务试图更新或删除数据时,而这些数据在此事务开始后被其他事务修改并提交时,DM 数据库将报“串行化事务被打断”错误。应用开发者应该充分考虑串行化事务带来的回滚及重做事务的开销,从应用逻辑上避免对相同数据行的激烈竞争导致产生大量事务回滚。并结合应用逻辑,捕获“串行化事务被打断”错误,进行事务重做等相应处理。如果系统中存在长时间运行的写事务,并且该长事务所操作的数据还会被其他短事务频繁更新的话,最好避免使用串行化事务。
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
executed successfully
used time: 0.380(ms). Execute id is 6223.
--查看隔离级别:
SQL> SELECT isolation FROM V$TRX;
LINEID ISOLATION
---------- -----------
5 3
---会话一
SQL> update yangkai1.tb1 set name='李二' where id=1;
affect rows 1
used time: 0.814(ms). Execute id is 6224.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522875 1 李二
used time: 0.314(ms). Execute id is 6225.
---会话二
SQL> SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
executed successfully
used time: 0.347(ms). Execute id is 6420.
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522873 1 王五
---会话一
SQL> commit;
executed successfully
used time: 1.380(ms). Execute id is 6226.
SQL>
--会话二
SQL> select TRXID,id,name from yangkai1.tb1 where id=1;
LINEID TRXID ID NAME
---------- -------------------- ----------- ------
1 7522873 1 王五
used time: 0.428(ms). Execute id is 6421.
--此时查询到的记录和之前一致,并没有因为会话一提交了记录发生改变
通过测试,达梦是支持设置4种隔离级别。
但是可重复读和串行读的隔离级别都是3,而且功能也是一样;
也就明白为什么官方手册说只支持3种。但是官方手册有个错误。
文章
阅读量
获赞