• oracle发生重启动的介绍


    2011年1月13日

    重启动发生的原因:where条件读取时采用一致读和更新时采取当前读版本不一致造成
    Oracle在执行DML语句时,会用到两种不同的方式去读取数据块:
    1. 一致读:在“找到”需要修改的数据行时,会采用 consistent read
    2. 当前读:在“获取”数据块来实际更新数据行时,会采用 current read

    如更新这个语句update test set x=1 where y=1;
    首先Oracle会利用一致读找到所有y=1的数据行,因此就算读取期间有别的会话修改了某一行的y值(如从y=1变为 y=2),
    Oracle也会利用undo数据将该行的y列恢复到读取的那个时刻的值(即y=1),所以这一行还是会被读取。然后,当要实际更新这一行的时候,
    Oracle会利用当前读去获取数据块的最新版本,由于被提交过了,所以读到的y值是2,与之前一致读中的y=1不符。
    所以Oracle就知道了需要 “重启动”这个update操作。

    Oracle重启动的流程:
    1. 回滚之前的修改操作
    2. 进入select for update模式,锁定需要修改的行
    3. 对锁定的行进行修改操作
    (这个流程是指在Oracle默认的READ COMMITED隔离级别下,如果是SERIALIZABLE模式,则会出现ORA-08177错误)

    重启动查看(通过创建触发器来查看)
    create table t (x int,y int);
    insert into t values(1,1);commit;
    create or replace trigger t_buffer before update on t for each row
    begin
     dbms_output.put_line ('old.x='||:old.x||',old.y='||:old.y);
     dbms_output.put_line ('new.x='||:old.x||',new.y='||:old.y);
    end;

    update t set x=x+1 where x>0;
    输出结果如下:
    old.x=1,old.y=1
    new.x=1,new.y=1

    在第二个会话中执行
    update t set x=x+1 where x>0; --被锁定
    将第一个会话中提交后,输出结果如下:
    old.x=1,old.y=1
    new.x=1,new.y=1
    old.x=2,old.y=1
    new.x=2,new.y=1

    where条件改成y=0也一样 在第一个会话中执行如下语句
    update t set x=x+1 where y>0;
    old.x=3,old.y=1
    new.x=3,new.y=1

    在第二个会话中执行
    update t set x=x+1 where y>0;
    old.x=3,old.y=1
    new.x=3,new.y=1
    old.x=4,old.y=1
    new.x=4,new.y=1

    修改触发器如下:
    create or replace trigger t_buffer before update on t for each row
    begin
     dbms_output.put_line ('已更新');
    end;

    第一个会话
    update t set x=x+1 where x>0;
    输出结果:
    已更新

    第二个会话
    update t set x=x+1 where x>0;
    输出结果:
    已更新
    已更新

    如果where条件改成y>0,那么就不会引发重启动
    第一个会话
    update t set x=x+1 where y>0;
    输出结果:
    已更新

    第二个会话
    update t set x=x+1 where y>0;
    输出结果:
    已更新

    结果说明:说明:old和:new值在触发器引用时,也会被oracle用于完成重启动检查。where子句中查找行所用的列集会与行触发器中引用的列进行比较,行的一致读版本会与行的当前读版本比较,只要不同,就会重启动修改。
    如果 after for each row 触发器比使用 before for each row 触发器更有效,如果使用after for each row 触发器就不会引发重启动问题。


     
  • 相关阅读:
    session
    jQuery使用ajaxStart()和ajaxStop()方法
    animate 的另一种用法 , 案例 等
    Javascript 面向对象编程(一):封装
    用事件委托获取每一个LI的索引值 有问题
    正常事件绑定与事件委托绑定
    JS 总结
    关于选项卡, 每一个TAB 标签 背景不一样的处理方式
    页面加载时的 Loading 效果
    一个计时器, 点击按钮 让他 停一会, 5s后继续自动运行
  • 原文地址:https://www.cnblogs.com/lanzi/p/1934708.html
Copyright © 2020-2023  润新知