并发与多版本:update重启动问题

以下演示重启动问题,请注意 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书籍

 

posted @ 2016-04-28 10:36  pompeii  阅读(334)  评论(0编辑  收藏  举报