【问题标题】:ORA-08177 with locked tableORA-08177 锁定表
【发布时间】:2013-11-24 04:38:59
【问题描述】:

之后

create table l (id int primary key, val int);
insert into l values (0, 0);

并初始化两个 oracle 会话

alter session set isolation_level=serializable;

以下继承导致ORA-08177: can't serialize access for this transaction

  session 1                           session 2                          
 -----------------------------------+-----------------------------------
  lock table l in exclusive mode                                         
 -----------------------------------+-----------------------------------
                                      lock table l in exclusive mode     
 -----------------------------------+-----------------------------------
  update l set val = 1 where id = 0   [blocked]                          
 -----------------------------------+-----------------------------------
  commit                              [blocked]                          
 -----------------------------------+-----------------------------------
                                      update l set val = 2 where id = 0  
 -----------------------------------+-----------------------------------
                                      [ORA-08177]                        

这是为什么呢?在我看来,它完全是连续的。

【问题讨论】:

    标签: oracle locking serializable


    【解决方案1】:

    当可序列化事务试图在可序列化事务开始后更改另一个事务(可序列化与否)已经更改的数据(或者甚至位于同一数据块中另一个事务已经更改的数据附近的数据)时,您'将收到ORA-08177 错误消息。当您将事务隔离级别设置为serializable 时,需要牢记两件重要的事情:

    1. 只有在可序列化事务(而不是语句)开始时已经提交了另一个事务对记录所做的更改时,可串行化事务才能更改记录。
    2. 读取一致性扩展到事务级别,而不是语句级别,因为当事务隔离级别设置为read committed(默认事务隔离级别)时。

    基本上,当可序列化事务开始时,它会获取自己的数据快照,提交的数据,并仅在该快照上操作,并且只看到自己提交的数据 - 在获取新的快照之前无法看到另一个事务提交的数据数据。并且在您结束(提交或回滚)一个可序列化事务并启动另一个事务后,将获取新的数据快照。

    导致ORA-08177 错误的简单示例:

    -- /* test table */
    SQL> create table t1(col) as 
           select 3 from dual;
    Table created.
    
    -- sqlplus session #1                     sqlplus #session 2
    ----------------------------------------------------------------------------
    SQL> alter session 
           set isolation_level=serializable;
    
                                              SQL> alter session set
                                                   isolation_level=serializable;
    
    /*
       You start serializable transaction by locking the t1 table in 
       exclusive mode. 
    
     */
    
    -- serializable transaction #1
    
    SQL> lock table t1 in exclusive mode;    -- serializable transaction # 2
                                             -- snapshot of t1 has been acquired
    SQL> update t1 set col = 5               SQL> lock table t1 in exclusive mode;
          where col = 3; 
                                             -- this update does not see changes 
    1 row updated.                           -- transaction #1 has already made 
                                             -- to t1's row where col = 3. 
                                             SQL> update t1 set col = 7 
    SQL> commit;                                   where col = 3;
                                             ERROR at line 1:
    Commit complete.                         ORA-08177: can't serialize access 
                                                        for this transaction 
    

    在上述情况下,Oracle 为了使您的数据库保持一致模式,会向您抛出ORA-08177,因为它知道可序列化事务#1 对@987654327 所在的行进行了更改@ 和可序列化事务 #2 尚未获取新的数据快照 - 对旧快照进行操作。

    同时使用显式排他表锁和可序列化事务似乎非常非常过分:a)对并发性的巨大打击; b) 为了避免ORA-08177,您需要提交或回滚引发ORA-08177错误的事务并重试,一旦您发出提交或回滚,排他表锁将立即释放。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2022-11-29
      • 2021-06-10
      • 2011-07-31
      • 2010-11-03
      • 1970-01-01
      相关资源
      最近更新 更多