并发与多版本: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书籍

 

转载于:https://www.cnblogs.com/pompeii2008/p/5441715.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值