• 测试oracle10g 的IO隔离级别serializable


    用sys用户给scott一个默认表空间
    create tablespace lisx datafile '+DATA' ;
    alter user scott default tablespace lisx ;

    建测试表
    create table dept
    (deptno number(9),
    deptname varchar2(20),
    detail   varchar2(50)
    );
    insert into dept values(1,'业扩','新装增容') ;
    insert into dept values(2,'账务','账务') ;
    insert into dept values(3,'电费','电费') ;
    insert into dept values(4,'质量','测试DBA打包') ;

    commit ;

    打开两个scott的会话
    在会话1里面:
    SQL> col deptname format a10 ;
    SQL> col detail format a20 ;
    SQL> select * from dept ;

        DEPTNO DEPTNAME   DETAIL
    ---------- ---------- --------------------
             1 业扩        新装增容
             2 账务         账务
             3 电费        电费
             4 质量        测试DBA打包

    SQL> show user       
    USER is "SCOTT"
    SQL>
    SQL>
    SQL> update dept set detail='账务2222' where deptno=2 ;

    1 row updated.

    然后在会话2里:
    SQL> set sqlprom 'SQL2>' ;
    SQL2>
    SQL2>col deptname format a10 ;
    SQL2>col detail format a20 ;
    SQL2>select * from dept ;

        DEPTNO DEPTNAME   DETAIL
    ---------- ---------- --------------------
             1 业扩        新装增容
             2 账务         账务
             3 电费        电费
             4 质量        测试DBA打包

    SQL2>update dept set detail='账务33333' where deptno=2 ; 

    如果第一个会话不提交,那么SQL2的修改会失败,一直等待前一个会话释放资源,形成了语句的死锁。

    如果会话一提交,那么会话2也可以成功执行,但是因为修改的标准是参照最初的值,所以会覆盖会话1的修改结果。我们称之为不可重复读(Non Repeatable Read)
    SQL>commit ;

    Commit complete.

    SQL2>commit ;

    Commit complete.

    下面在第二个会话设置
    SQL2>alter session set isolation_level=serializable ;
    我们看看设置IO隔离级别后的效果,主要是看看能否避免丢失修改。

    SQL2>select * from dept ;

        DEPTNO DEPTNAME   DETAIL
    ---------- ---------- --------------------
             1 业扩        新装增容
             2 账务         账务33333
             3 电费        电费
             4 质量        测试DBA打包

    在会话1里设置IO隔离级别
    SQL>alter session set isolation_level=serializable ;

    Session altered.

    SQL> update dept set detail='44444' where deptno=2 ;

    1 row updated.

    先不提交,在会话2里面执行
    SQL2>update dept set detail='55555' where deptno=2 ;
    该修改会处于等待状态
     
    然后提交会话1
    SQL> commit ;

    Commit complete.

    会话2里面报错了:
    SQL2>update dept set detail='55555' where deptno=2 ;
    update dept set detail='55555' where deptno=2
           *
    ERROR at line 1:
    ORA-08177: can't serialize access for this transaction

    因此通过设置会话1的隔离级别isolation_level=serializable,避免了其他会话的修改丢失。
    理论上serializable还能避免幻影读,但是幻影读不太好实现。
    SQL标准中定义了4中IO隔离级别
    READ Uncommited
    READ Commited  避免了脏读
    Repeatable     避免了脏读,不可重复读
    Serializable   避免了脏读,不可重复读,幻影读

    但是ORACLE只有3中:
    READ Commited
    Serializable
    Read Only

    对于READ Uncommited,oracle无法模拟。
    对于Repeatable,ORACLE可以通过悲观锁和乐观锁实现Repeatable
    Read Only和Serializable的区别是对于丢失修改,前者是禁止修改,后者报错:
    ORA-08177: can't serialize access for this transaction

  • 相关阅读:
    大爽Python入门教程 0-2 什么是IDE?python选什么IDE好?
    大爽Python入门教程 0-3 安装Atom与配置Python环境
    大爽Python入门教程 0-1 安装python
    HBase 过滤器 及shell 操作过滤器
    分布式ID生成方式(雪花算法)
    tidb 踩坑经验(转载)
    MYSQL ACID
    kafka什么时候会丢消息
    java 单例模式模式实现
    使用 GitHub 的十个最佳实践
  • 原文地址:https://www.cnblogs.com/caibird2005/p/1691768.html
Copyright © 2020-2023  润新知