事务中的丢失更新

丢失更新的定义:当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,会发生丢失更新问题。每个事务都不知道其他事务的存在。最后的更新将覆盖由其他事务所做的更新,这将导致数据丢失。

典型事务序列是:

       begin Transaction;
       select col_value into :var_col_value from tableA where keyid=:keyid;
       ......

       var_col_new_value=var_col_value+1 
       update tableA set col_value=:var_col_new_value where keyid=:keyid;
       commit;

丢失分析:

  • update更新依赖于select选定的行
  • 更新的值依赖于select的结果
  • 有多个事务存在,另外一个事务的select可能出现在:
    • 本事务的select之后,update之前
      • 如果允许读,读到的依然是var_col_value,必然发生丢失
    • 本事务的update之后,commit之前
      • 如果允许脏读,读到的是var_col_new_value,但是存在脏写,依然不安全
      • 如果允许读,但不是脏读,读到的依然是var_col_value,必然发生丢失
    • 本事务的commit之后
      • 读到的是var_col_new_value,不会丢失

防止丢失:

  • 针对简单类型及逻辑:
    • 更改update SQL语句为累加,即
    • update tableA set col_value=col_value+1 where keyid=:keyid;
  • 不能改变SQL时,需要把select延迟到commit之后
    • 提升事务隔离级别
      • 可重复读Repeatable read
      • 可序列化Serializable
posted @ 2010-12-13 14:31  玩玩乐乐  阅读(470)  评论(0编辑  收藏  举报