我试图看看我是否可以使用数据库锁来处理竞争条件。例如
CREATE TABLE ORDER
(
T1_ID NUMBER PRIMARY KEY,
AMT NUMBER,
STATUS1 CHAR(1),
STATUS2 CHAR(1),
UPDATED_BY VARCHAR(25)
);
insert into order values (order_seq.nextval, 1, 'N', 'N', 'U0');
后来两个用户可以同时更新订单记录。要求是只有一个可以继续而另一个不应该继续。我们当然可以使用分布式锁管理器(DLM)来做到这一点,但我认为数据库锁可能更有效。
用户1:
update T1 set status1='Y', updated_by='U1' where status1='N';
用户2:
update T1 set status2='Y', updated_by='U2' where status1='N';
两个用户正在同时进行这些操作。理想情况下,只允许一个人继续进行。我使用Sql Plus玩,还编写了一个小的java测试程序,让两个线程同时执行这些操作。我得到了相同的结果。让我们说用户1首先获得数据库行锁定。它返回1行更新。在第一个会话提交或回滚之前,将阻止第二个会话等待行锁定。问题是真的这样:
使用where子句进行更新似乎有两个操作:首先,它将根据where子句执行隐式选择,以选择将要更新的行。由于Oracle仅支持READ COMMITTED隔离级别,因此我希望两个UPDATE语句都将选择DB中的单个记录。因此,我预计UPDATE语句最终将返回" 1行更新"虽然会等到另一个事务提交。然而,这不是我所看到的。第二个UPDATE返回" 0行更新"在第一次提交之后。我觉得Oracle在第一次会话提交后实际运行了where子句AGAIN,这导致" 0行更新"结果
这对我来说很奇怪。我以为我会遇到经典的"丢失的更新"现象。
有人可以解释一下这里发生了什么吗?非常感谢!