select for update丢失更新

Normal 0 7.8 磅 0 2 false false false EN-US ZH-CN X-NONE select 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 2commit;释放锁。

现在我们稍微修改下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博客 ” ,链接:http://blog.itpub.net/16566331/viewspace-670127/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/16566331/viewspace-670127/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值