oracle事务隔离级别_笔记10:查看重启动
查看重启动
查看重启动可以用一个单行表来观察。
scott@ORCL>create table t(x int,y int);
Table created.
scott@ORCL>insert into t values(1,1);
1 row created.
scott@ORCL>commit;
Commit complete.
为了观察重启动,只需要一个触发器打印出一些信息。使用一个BEFORE UPDATE FOR EACH ROW触发器打印出行的前映像和作为更新结果的后映像:
scott@ORCL>create or replace trigger t_bufer
2 before update on t for each row
3 begin
4 dbms_output.put_line
5 ('old.x=' || :old.x ||
6 ',old.y=' || :old.y);
7 dbms_output.put_line
8 ('new.x=' || :new.x ||
9 ',new.y=' || :new.y);
10 end;
11 /
Trigger created.
下面可以更新这一行:
scott@ORCL>set serveroutput on
scott@ORCL>update t set x=x+1;
old.x=1,old.y=1
new.x=2,new.y=1
1 row updated.
触发器每触发一次,我们都可以看到旧值和新值。不过,要注意,此时还没有提交,这一行仍被锁定。在另一个会话中,执行以下更新
scott@ORCL>set serveroutput on
scott@ORCL>update t set x=x+1 where x>0;
当然,这会立即阻塞,因为第一个会话将这一行锁住了。如果现在回到第一个会话,并提交,会看到第二个会话中有以下输出:
old.x=1,old.y=1
new.x=2,new.y=1
old.x=2,old.y=1
new.x=3,new.y=1
1 row updated.
可以看到,行触发器看到这一行有两个版本。行触发器会触发两次:一次提供了行原来的版本以及我们想把原来这个版本修改成什么,另一次提供了最后实际更新的行。由于这是一个BEFORE FOR EACH ROW触发器,Oracle看到了记录的读一致版本,以及我们想对它做的修改。不过,Oracle以当前模式获取块,从而在BEFORE FOR EACH ROW触发器触发之后具体执行更新。它会等待触发器触发后再以当前模式得到块,因为触发器可能会修改:NEW值。因此Oracle在触发器执行之前无法修改这个块,而且触发器的执行可能要花很长时间。由于一次只有一个会话能以当前模式持有一个块,所以Oracle需要对处于当前模式下的时间加以限制。
触发器触发后,Oracle以当前模式获取这个块,并注意到用来查找这一行的X列已经修改过。由于使用了X来定位这条记录,而且X已经修改,所以数据库决定重启动查询。注意,尽管X从1更新到2,但这并不会使该行不满足条件(x>0),这条UPDATE语句还是会更新这一行。而且,由于X用于定位这一行,而X的一致读值(这里是1)不同于X的当前模式读值(2),所以在重启动查询时,触发器把值X=2(被另一个会话修改之后)看做是:OLD值,而把X=3看做是:NEW值。
由此就可以看出发生了重启动。要用触发器查看实际的情况;否则,重启动一般是“不可检测的”。这并不是说无法看到重启动的其他症状,例如更新多行时,发现某一行会导致重启动,而导致一个很大的UPDATE语句回滚工作,这也可能是一个症状,但是很难明确地指出“这个症状是重启动造成的”
本文来源 我爱IT技术网 http://www.52ij.com/jishu/5227.html 转载请保留链接。
- 评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)
-
