并发事务下各数据库外部表现实测之二(Oracle篇)
2013-09-16 08:36
218 查看
Oracle采用MVCC技术进行事务隔离,它只支持2种隔离级别,读已提交和可串行化,设置其他隔离级别会报错。这种基于MVCC的可串行化也被称为SNAPSHOT
ISOLATION(SI)。就像SNAPSHOT的字面意思一样,MVCC像是给每个事务保留一个快照,对于数据的读取可以不受其他事务的影响。读已提交和可串行化的区别在于SNAPSHOT采取的时点,前者在SQL执行时,后者在事务开始时。下面参照之前的做法也对Oracle事务进行实测。
1. 测试环境
OS:RHEL6
DBMS:Oracle 11g
2. 测试结果t.163.com查询
读已提交:
OK(**):基于更新前的数据,即看到是查询时的快照
等待(*):如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据
注:黄色代表和SQL Server 的READ_COMMITTED_SNAPSHOT=ON时的读已提交不同的地方
从上面的表可以看出,Oracle 的读已提交比SQL Server的READ_COMMITTED_SNAPSHOT=ON时的读已提交基本上差不多,但处理插入时阻塞的可能性更小。
可串行化:
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 亦然。
ISOLATION(SI)。就像SNAPSHOT的字面意思一样,MVCC像是给每个事务保留一个快照,对于数据的读取可以不受其他事务的影响。读已提交和可串行化的区别在于SNAPSHOT采取的时点,前者在SQL执行时,后者在事务开始时。下面参照之前的做法也对Oracle事务进行实测。
1. 测试环境
OS:RHEL6
DBMS:Oracle 11g
2. 测试结果t.163.com查询
读已提交:
先执行SQL\后执行SQL | 同一行查询 | 非同行查询 | 整表查询 | 同一行插入 | 非同行插入 | 同一行更新 | 非同行更新 | 整表更新 | 同一行删除 | 非同行删除 | 整表删除 |
单行查询 | 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(**) | 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 | OK(**) | 等待(*) | OK | 等待(*) | OK | 等待(*) | 等待(*) | OK | 等待(*) |
等待(*):如果先行的SQL提交,则基于更新后的数据,否则基于原来的数据
注:黄色代表和SQL Server 的READ_COMMITTED_SNAPSHOT=ON时的读已提交不同的地方
从上面的表可以看出,Oracle 的读已提交比SQL Server的READ_COMMITTED_SNAPSHOT=ON时的读已提交基本上差不多,但处理插入时阻塞的可能性更小。
可串行化:
先执行SQL\后执行SQL | 同一行查询 | 非同行查询 | 整表查询 | 同一行插入 | 非同行插入 | 同一行更新 | 非同行更新 | 整表更新 | 同一行删除 | 非同行删除 | 整表删除 |
单行查询 | 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(***) | 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 | OK(***) | 等待(*) | OK | 等待(**) | OK | 等待(**) | 等待(**) | OK | 等待(**) |
等待(*):如果先行的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 亦然。
相关文章推荐
- Oracle 数据库中不同事务并发访问的问题
- 数据库的事务并发、事务隔离级别
- 数据库并发访问、事务与锁、脏读、不可重复读、幻影读
- oracle 事务简介,锁的概念,java访问数据库注意事项
- 数据库事务并发带来的问题、及并行
- Oracle 数据库事务隔离级别概述
- 数据库事务并发:概述
- 万能数据库查询分析器中的事务管理在Oracle中的应用
- oracle---创建数据库、事务操作、备份
- 在 .NET 中使用 oracle 数据库 事务提交,事务保存点
- oracle分布式处理时报“ORA-02041: 客户数据库未开始一个事务处理”解决办法 - z
- 正好整理了一下,自己做了个连接数据库的组件,支持SQLSERVER,ACCESS,ORACLE,FoxPro,MySql,IBM DB2,DBF等数据库,并且支持事务处理
- oracle多用户并发及事务处理
- 数据库系统原理复习题(八)——事务并发控制
- 使用事务码DBCO实现SAP链接外部数据库以及读取例程
- 数据库(Hibernate)事务与并发问题处理(乐观锁与悲观锁)
- 数据库并发机制和事务的隔离级别详解
- MS SQL Server和Oracle对数据库事务处理的差异性
- Spring事务之二(JDBC连接数据库的四种方式)
- oracle 连接外部数据库配置