并发事务下各数据库外部表现实测之二(Oracle篇)

来源:互联网 发布:软件开发是什么意思? 编辑:程序博客网 时间:2024/06/05 00:32
Oracle采用MVCC技术进行事务隔离,它只支持2种隔离级别,读已提交和可串行化,设置其他隔离级别会报错。这种基于MVCC的可串行化也被称为SNAPSHOT ISOLATION(SI)。就像SNAPSHOT的字面意思一样,MVCC像是给每个事务保留一个快照,对于数据的读取可以不受其他事务的影响。读已提交和可串行化的区别在于SNAPSHOT采取的时点,前者在SQL执行时,后者在事务开始时。下面参照之前的做法也对Oracle事务进行实测。

1. 测试环境
OS:RHEL6
DBMS:Oracle 11g

2. 
测试结果t.163.com查询
读已提交:

先执行SQL\后执行SQL同一行查询非同行查询整表查询同一行插入非同行插入同一行更新非同行更新整表更新同一行删除非同行删除整表删除单行查询OKOKOK主键冲突OKOKOKOKOKOKOK整表查询OKOKOK主键冲突OKOKOKOKOKOKOK插入

OK(**)

OK

OK(**)

等待(*)OKOK(**)OKOK(**)OK(**)OKOK(**)单行更新

OK(**)

OK

OK(**)

主键冲突OK等待(*)OK等待(*)等待(*)OK等待(*)整表更新

OK(**)

OK

OK(**)

主键冲突OK等待(*)OK等待(*)等待(*)OK等待(*)单行删除

OK(**)

OK

OK(**)

等待(*)OK等待(*)OK等待(*)等待(*)OK等待(*)整表删除

OK(**)

OK

OK(**)

等待(*)OK等待(*)OK等待(*)等待(*)OK等待(*)OK(**):基于更新前的数据,即看到是查询时的快照
等待(*):
如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据
注:黄色代表和SQL Server 的READ_COMMITTED_SNAPSHOT=ON时的读已提交不同的地方
从上面的表可以看出,Oracle 的读已提交比SQL Server的READ_COMMITTED_SNAPSHOT=ON时的读已提交基本上差不多,但处理插入时阻塞的可能性更小。

可串行化

先执行SQL\后执行SQL同一行查询非同行查询整表查询同一行插入非同行插入同一行更新非同行更新整表更新同一行删除非同行删除整表删除单行查询OKOKOK主键冲突OKOKOKOKOKOKOK整表查询OKOKOK主键冲突OKOKOKOKOKOKOK插入

OK(***)

OK

OK(***)

等待(*)OKOK(***)OKOK(***)OK(***)OKOK(***)单行更新

OK(***)  

OK

OK(***)

主键冲突OK等待(**)OK等待(**)等待(**)OK等待(**)整表更新

OK(***)

OK

OK(***)

主键冲突OK等待(**)OK等待(**)等待(**)OK等待(**)单行删除

OK(***)

OK

OK(***)

等待(*)OK等待(**)OK等待(**)等待(**)OK等待(**)整表删除

OK(***)

OK

OK(***)

等待(*)OK等待(**)OK等待(**)等待(**)OK等待(**)OK(***):基于更新前的数据,查询看到的是事务开始时的快照event
等待(*):
如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据info
等待(**):如果先行的SQL提交,则报更新冲突的错误,"ORA-08177: 无法连续访问此事务处理" 
注:黄色代表和读已提交不同的地方eventId

3.  Oracle的串行化(SI)和真正串行化的区别

Oracle的串行化(SI)其实等同于SQL Server的SNAPSHOT,它满足SQL标准对可串行化的要求,但并不是真正的可串性化。下面用一个例子来说明

/-5777896639697768785
/341018209886538040
/-248752558554698112
/3695141408112736151
/-7997662361159449950
/212821422613202010
/-294409163655268084
/4518187912517456276
/-6258722245610832837
/7555051128934922001
/-2563812029577661172
/-8987855923191418848
/-6535855513250128448
/7647637506402175787
/-5999989679990946649
/-524696247291654558
/4519174811055014556
/932422716846628974
/298578870777511097
/-4858117309282232497
/3581843498415465799
/-1130885605335979942
/4263705493882513384
/-1335960542939031169
/-483360142662101861

SI下,2个事务按下面的顺序交替执行,可以执行成功。


SI下,2个事务按下面的顺序交替执行,可以执行成功。
1) 事务1:select * from tb1;
2) 事务2:select * from tb1;
3) 事务1:insert into tb1 values(5,'a');
4) 事务2:insert into tb1 values(6,'a');
5) 事务1:commit;
6) 事务2:commit;

但是这不符合真正的串行化。如果2个事务按照 事务1->事务2 的顺序串行执行, 在2)中事务2应该能看到3)事务1插入的数据,这是不可能的;反之 事务2->事务1 亦然。
原创粉丝点击