开发人员的在代码中使用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博客 ” ,链接:http://blog.itpub.net/16566331/viewspace-670127/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16566331/viewspace-670127/