ITPub博客

首页 > Linux操作系统 > Linux操作系统 > select for update丢失更新

select for update丢失更新

原创 Linux操作系统 作者:os-ora 时间:2010-08-03 17:13:17 0 删除 编辑
Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONEselect for update丢失更新

开发人员的在代码中使用select for update来防止丢失更新。然而在测试时还是发生了丢失更新的情况。
经过模拟。重现了问题的出现。跟大家分享下。


Session 1

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> select * from t;

       TID TNAME                          TTIME
---------- ------------------------------ ---------
         1 Y                              24-NOV-09
         2 Y                              24-NOV-09
         3 Y                              24-NOV-09
         4 Y                              24-NOV-09
         5 Y                              24-NOV-09
         6 Y                              24-NOV-09
         7 Y                              24-NOV-09
         8 Y                              24-NOV-09
         9 Y                              24-NOV-09
        10 Y                              24-NOV-09

10 rows selected.

SQL> select tid from t
  2   where tid =(
  3     select tid from (
  4        select tid from t T01
  5         where tname='Y'
  6      order by tid)
  7         where rownum<2)
  8   for update;

       TID
----------
         1



Session 2

Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options

SQL> select tid from t
  2   where tid =(
  3     select tid from (
  4        select tid from t T01
  5         where tname='Y'
  6      order by tid)
  7         where rownum<2)
  8   for update;
现在session 2会挂起,因为SESSION1加锁在tid=1的列上。
OK
,在SESSION 1上执行

SQL> update t set tname='N1' where tid=1;

1 row updated.

SQL> commit;

Commit complete.
现在锁已经释放了,转到session2,看看session 2的结果。

       TID
----------
         1

Session 1
提交的数据并没有影响到在session 2的查询。
此时如果在TID=1的列上做更新,则SESSION 1的更新就丢失。
丢失更新出现鸟。
在session 2上commit;释放锁。

现在我们稍微修改下SQL
SESSION 1
执行

SQL> select tid,TNAME from t
  2   where tid =(
  3     select tid from (
  4        select tid from t T01
  5         where tname='Y'
  6      order by tid)
  7         where rownum<2)
  8   for update;

       TID TNAME
---------- ------------------------------
         2 Y
转到session 2

SQL> select tid,TNAME from t
  2   where tid =(
  3     select tid from (
  4        select tid from t T01
  5         where tname='Y'
  6      order by tid)
  7         where rownum<2)
  8   for update;
Session 2
挂起
在session 1上执行
SQL> update t set tname='N1' where tid=2;

1 row updated.

SQL> commit;

Commit complete.

SQL>
释放了悲观锁定。现在转到session 2. 查询出结果了。
       TID TNAME
---------- ------------------------------
         3 Y
此时session 1 的commit修改结果影响到了session 2的查询。不再有丢失更新。

或者我们还可以使用 for update of tname.
或者采用一个select null from temp1 for update,两个会话都,将锁定提前,也可以避免丢失更新的情况。(temp1是只负责串行,不要做其他用途)

 

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/16566331/viewspace-670127/ ,如需转载,请注明出处,否则将追究法律责任。

上一篇: rman备份脚本
请登录后发表评论 登录
全部评论

注册时间:2010-01-12

  • 博文量
    148
  • 访问量
    410403