ITPub博客

首页 > 数据库 > Oracle > oracle小知识点2--一致性读中的重启动更新

oracle小知识点2--一致性读中的重启动更新

原创 Oracle 作者:selectshen 时间:2015-06-19 18:08:30 0 删除 编辑
以下三个问题,个人觉得很有趣,如果没有了解oracle的重启动更新,可能会对查询结果感到怀疑~
--oracle version:11.2.0.2.0
--问题一:
----建测试表
create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;
----查询结果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1执行:
update scott.test01
set a=3
where a<3;

----session 2执行:
update scott.test01
set a=2
where a=3;

----session 1执行:
commit;

----session 2执行:
commit;

----session 1执行:
select * from scott.test01;
----此处session 1的查询结果是
/*
3
3
2
*/
问题一的结果,说明session 1的update没有影响到session 2的update
session 1 update后,根据一致性读,session 2看到的还是没有更新过的结果.session 2做update操作锁定的行与session 1 update时锁定的行不相同.
session 1 commit提交要更新的行,并释放锁,session 2 commit提交要更新的行,并释放锁,相互之间不影响.

--问题二:
----建测试表
drop table scott.test01 purge;

create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;

----查询结果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1执行:
update scott.test01
set a=1
where a>1;

----session 2执行:
update scott.test01
set a=4
where a<3;

----session 1执行:
commit;

----session 2执行:
commit;
----session 1执行:
select * from scott.test01;
----此处session 1的查询结果是什么?
/*
4
4
4
*/
问题二的结果,说明session 1的update影响到session 2的update
session 1 update后,根据一致性读,session 2看到的还是没有更新过的结果.session 2做update操作锁定行时,与session 1 update时锁定的行在a=2这一行是相同的,此时session 2会被阻塞,等待session 1 commit或rollback.
session 1 commit提交要更新的行,并释放锁.
重点来了,由于session 1提交后,session 2要锁定的行对应的where a<3中a的值有变更,此时oralce内部会回滚更新,并重启动更新,因为原本a=3被session 1更新为a=1,所以在重启动
更新时也会被where a<3所包含,最后三条记录全部被更新了.

--问题三:
----建测试表
drop table scott.test01 purge;

create table scott.test01
as select 1 a from dual
union all select 2 from dual
union all select 3 from dual;
----查询结果
select * from scott.test01;
/*
A
1
2
3
*/

----session 1执行:
update scott.test01
set a=2
where a>1;

----session 2执行:
update scott.test01
set a=4
where a<3;

----session 1执行:
commit;

----session 2执行:
commit;
----session 1:
select * from scott.test01;
----此处session 1的查询结果是什么?
/*
4
4
2
*/
问题三的结果,说明session 1的update没有影响到session 2的update
session 1 update后,根据一致性读,session 2看到的还是没有更新过的结果.session 2做update操作锁定行时,与session 1 update时锁定的行在a=2这一行是相同的,此时session 2会被阻塞,等待session 1 commit或rollback.
session 1 commit提交要更新的行,并释放锁.
由于session 1提交后,session 2要锁定的行对应的where a<3中a有更新,但a=2的值没有变更,此时oralce不需要回滚更新,所以更新之前锁定的两行,原本a=3的行虽然在session 1中已经被更新为2满足where a<3,但由于没有重启动更新,就不会更新这一行.

--备注:
这样看来,重启动更新 依赖于会话之间的行锁阻塞及where条件中的值变更.在计算结果的时候,要结合rowid和where条件一起比较容易判断.重启动更新可以通过触发器扑捉到.

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/28539951/viewspace-1705502/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: mysql with keepalived
请登录后发表评论 登录
全部评论

注册时间:2014-01-05

  • 博文量
    169
  • 访问量
    1567873