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