以下演示重启动问题,请注意 before触发器和after触发器的行为区别,因为before触发器会触发两次而导致重启动问题,因此使用after触发器更加高效,应该尽量避免在所有触发器中使用自治事务
-------演示before触发器导致的查询重启动问题
1、创建测试表
create table test4(x number, y number);
insert into test4 values (1,4);
commit;
2、创建before触发器
create or replace trigger t4
before update on test4 for each row
begin
dbms_output.put_line('old.y-->'||:old.y);
dbms_output.put_line('new.y-->'||:new.y);
end;
3、执行更新
session 1:
SQL> select vm.*,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from v$mystat vm where rownum =1;
SID STATISTIC# VALUE TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
---------- ---------- ---------- ------------------------------
13 0 0 2016-04-28 10:05:44
SQL> update test4 set y=y+1 where x=1;
old.y-->4
new.y-->5
1 row updated
---注:此时不提交
session 2:
SQL> select vm.*,to_char(sysdate,'yyyy-mm-dd hh24:mi:ss') from v$mystat vm where rownum =1;
SID STATISTIC# VALUE TO_CHAR(SYSDATE,'YYYY-MM-DDHH2
---------- ---------- ---------- ------------------------------
73 0 0 2016-04-28 10:07:31
SQL> update test4 set y=y+1 where x=1;
---此时session2 会被session阻塞,一直等待session1提交或回滚;
返回至session1,执行提交;
SQL> commit;
Commit complete
---此时切换到session2查看,发现before 触发器打印的信息有点奇怪,这个现象就是重启动
old.y-->4
new.y-->5
old.y-->5
new.y-->6
1 row updated
4、修改before触发器,不使用:old和:new,再次重复上述1~3过程,发现不在出现重启动现象
create or replace trigger t4
before update on test4 for each row
begin
dbms_output.put_line('this is before trigger');
end;
session1:
SQL> update test4 set y=y+1 where x=1;
this is a before trigger
1 row updated
session2:
SQL> update test4 set y=y+1 where x=1;
this is a before trigger
1 row updated (此时被session1阻塞)
返回session1执行提交:
SQL> commit;
Commit complete
返回session2查看结果:
SQL> update test4 set y=y+1 where x=1;
this is a before trigger
1 row updated
-------演示after触发器不会导致查询重启动
1、先drop before 触发器:
SQL> drop trigger t4;
Trigger dropped
2、创建after触发器:
create or replacetrigger t5
after update on test4 for each row
begin
dbms_output.put_line( 'old.y-->'||:old.y);
dbms_output.put_line('new.y-->'||:new.y);
end;
3、执行更新
session1:
SQL> update test4 set y=y+1 where x=1;
old.y-->7
new.y-->8
1 row updated
session2:
SQL> update test4 set y=y+1 where x=1; ---由于session1未提交,session2此时被阻塞
返回session1,执行提交:
SQL> commit;
Commit complete
返回session2 查看结果:
old.y-->8
new.y-->9
1 row updated
注:此时并没有输出4行,而只是输出2行
----以上信息来自tom书籍