现在的位置: 首页 > 综合 > 正文

oracle锁机制的延续——并发与多版本2

2013年02月28日 ⁄ 综合 ⁄ 共 1756字 ⁄ 字号 评论关闭

5、一致性读和当前读的深入理解:

在CSDN里经常会遇到一些特别有学习劲头的朋友,有这样一个朋友,在学习Tom的经典书 

《oracle 9i/10g编程艺术》 人民邮电出版的 
P244 --7.4 写一致 

在一致性读 这里遇到些困惑,如下

引用:

create table t ( x int, y int ); 
insert into t values ( 1, 1 ); 
commit; 
create or replace trigger t_bufer 
before update on t for each row 
begin 
dbms_output.put_line 
( 'old.x = ' || : old.x || 
', old.y = ' || : old.y ); 
dbms_output.put_line 
( 'new.x = ' || :new.x || 
', new.y = ' || :new.y ); 
end; 

上面是观察重启动更新触发器 

sql1 : UPDATE t SET x = 2 WHERE y = 5; 

如果 在更新sql1时,别的会话也在更新这条记录并且把y=5更新也了 y=10 
这样oracle 会选择重启动更新,但重启动更新还是有可能会遇到同样的问题

这是一个非常经典的一段描述一致性读和写一致性的段落 

看到这么认真的朋友,也激起了我的解答欲。 

其实在oracle里保证一致性读写的特点,我自己是通过两个小点来进行归纳的 
1. 一致读(Consistent read):“发现”要修改的行时,所完成的获取就是一致读。 
2. 当前读(Current read):得到块来实际更新所要修改的行时,所完成的获取就是当前读。 

对于query里的查询是一致性读,这时是没有脏数据的。 对于update的时候,重新启动查询,避免脏数据写。 

根据这个基本原则,我们一起来做做实验,还是先用上面的trigger,注意这里的trigger和我们这里的知识点没有必然的联系,只是为了更清楚的表现出重新查询这个动作,我们加入的一个类似log的方式。 

我们还是用上面的sql来作为例子 
不过这里关键的是执行顺序 

哪个语句在前面执行, 现在数据库里的数据如下 
Data 
X Y 
4 5 

update的语句有两条 
SQL1: UPDATE t SET x = 2 WHERE y = 5; 
SQL2: UPDATE t SET y=y+1; 

如果sql1先执行,那么后面一句sql2 因为会同样update到 y=5的记录,这是sql1还没有提交,读一致性,不会读脏数据库,所以y=5还在,因此sql2会hold住. 
我们来提交sql1.看看结果如何 
当sql1提交时,sql1执行成功, 数据更新了x=2, 对于sql2来说重启动查询。用新值更新,不过sql1来说y没有发生改变,当SQL2也更新的时候,y是在原值上+1 
这时候数据库的值为 
X->2 (SQL1作用) 
Y->Y+1 (SQL2作用) 
X Y 
2 6 
现在我们反过来,还是用刚才的数据 
先执行sql2, 然后执行sql1 看看是怎样的 

先执行sql2,由于sql1读一致性,现在脏数据没有提交,读一致性,找到y=5的一条记录,进行更新,所以sql1现在hold住了。当 sql2提及以后, 数据库更新成功y=5已经变成了6叻。 sql1会如果操作了,很简单,对于update的动作来说,重新查询,这时由于重新查询,已经找不到要更新的y=5的记录了,这样也就一条记录都不会 update。 

数据库现在的变化为 
Y->Y+1 (SQL2作用) 
X->4 (SQL1作用) y=5的记录没有叻,所以更新0条记录。 

这也就是上面2点的真实表现了。 

Oracle 处理修改语句时会完成两类块获取。它会执行: 
一致读(Consistent read):“发现”要修改的行时,所完成的获取就是一致读。 
当前读(Current read):得到块来实际更新所要修改的行时,所完成的获取就是当前读。 

对这样的知识点,是不是大家都这样认真的思考过,总结过了,其实学习就是这样的。当你激发了自己的潜能和兴趣,你会变着法思考着里面的内容 

有兴趣的朋友可以,试想一下 
这样的case将是这样的结果?

引用:

数据库数据 
X Y 
---------- ---------- 
2 5 

SQL1 
Update t set x = 4 where y = 5; 

SQL2 
Update t set y = 6 where x = 2

抱歉!评论已关闭.