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

  • 相关阅读:
    Go 函数方法
    rz上传文件乱码
    pip问题:ImportError: cannot import name main
    docker启动报错 docker: Error response from daemon: OCI runtime create failed: container_linux.go:348
    python遍历列表删除多个元素的坑
    python写入csv文件时的乱码问题
    python中的exec()函数和eval()函数
    tornado的IOLoop.instance()方法和IOLoop.current()方法区别
    安装mysql-python时报错
    python将科学计数法表示的数值的字符串转换成数值型数据
  • 原文地址:https://www.cnblogs.com/pompeii2008/p/5441715.html
Copyright © 2020-2023  润新知