来演示一下写一致性的查询重启动。
session 1:
------------
C:\Documents and Settings\Administrator>sqlplus /nolog
SQL*Plus: Release 9.2.0.8.0 - Production on 星期二 12月 25 21:19:28 2007
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connhujinpei/passw0rd@icmnlsdb
已连接。
SQL> create table t ( x int , y int);
表已创建。
SQL> insert into t values (1 ,1);
已创建 1 行。
SQL> commit;
提交完成。
创建一个trigger来,观察重启动
SQL> create or replace trigger t_buffer
2 before update on t for each row
3 begin
4 dbms_output.put_line('old.x = '||:old.x||', old.y = '||:old.y);
5 dbms_output.put_line('new.x = '||:new.x||', new.y = ' || :new.y);
6 end;
7 /
触发器已创建
SQL> set serveroutput on
SQL> update t set x=x+1;
old.x = 1, old.y = 1
new.x = 2, new.y = 1
已更新 1 行。
SQL> update t set x=x+1;
old.x = 2, old.y = 1
new.x = 3, new.y = 1
已更新 1 行。
SQL> update t set x=x+1;
old.x = 3, old.y = 1
new.x = 4, new.y = 1
已更新 1 行。
这个时候我们切换到session 2:
C:\Documents and Settings\Administrator>sqlplus /nolog
SQL*Plus: Release 9.2.0.8.0 - Production on 星期二 12月 25 21:19:54 2007
Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.
SQL> connhujinpei/passw0rd@icmnlsdb
已连接。
SQL> set serveroutput on
SQL> update t set x=x+10 where x>0;
old.x = 1, old.y = 1
new.x = 11, new.y = 1
old.x = 4, old.y = 1
new.x = 14, new.y = 1
已更新 1 行。
我们发现trigger被触发了两次
分析:
其实session 2的更新经历了consistent read和current read两个过程。由于session 1的transaction因为没有提交而阻塞了session 2的更新,session 2开始执行update的时候就被session 1阻塞了,但是我们发现session 2会在where条件中寻找current read开始时数据库已经提交的transaction,这个时候x的value是1,所以new.x=11。而当session 1提交后,oracle会重新启动查询更新。
而如果session 1没有提交而是回滚了呢。那么trigger就被触发一次。