我有一个回调机制,基本上从给定匹配条件的表中获取一行,执行一些操作并基于行记录中的删除标记删除该行。
问题是在此系统中可能存在多个具有相同匹配条件的并发回调。我想要实现的是,在第一个回调中,当我选择要处理的行时(基于删除标记,此行可能会被删除或者在处理后没有删除),我希望其他回调等待。换句话说,我希望在表的行上有一个读锁定,如果在第一个回调中确实删除了它,那么第二个回调就无关紧要了它应该通过。
我在这里使用JDBC来执行这些操作。
答案 0 :(得分:3)
您可以使用the for update
clause锁定您选择的行。尝试检索相同行的第二个会话(也具有for update
)将默认阻止,直到您通过提交或回滚来释放锁。
所以会话1确实:
select column1, column2, ... from your_table where ... for update;
并且可以处理结果。虽然它正在进行第2次会议但是:
select column1, column2, ... from your_table where ... for update;
但现在会阻止,直到会话1释放锁。
作为一个简单的演示,让我们有一个小桌子:
create table t42 (id number, delete_flag varchar2(1));
insert into t42 values (1, 'N');
insert into t42 values (2, 'N');
insert into t42 values (3, 'Y');
commit;
在第1节:
SQL> select * from t42 where delete_flag = 'Y' for update;
ID D
---------- -
2 Y
3 Y
在第2节:
SQL> select * from t42 where delete_flag = 'Y' for update;
......就在那里等待。
返回会话1,删除您处理的其中一行:
SQL> delete from t42 where id = 2;
1 row deleted.
第二场会议仍在等待。假设出于某种原因,您只想删除那一行并将另一行留在那里,以便回调事务完成。现在在第1节:
SQL> commit;
Commit complete.
立即会议2现在报告:
ID D
---------- -
3 Y
当释放锁时,会重新执行查询,因此它会查看当前提交的数据,而不是提交命令时存在的(锁定)数据。
会话2现在已锁定该行,其他会话仍将被阻止,等待该会话提交或回滚。如果会话1删除了它已锁定的两个行,则会话2将看到“没有选择行”并且没有行锁(尽管它仍然会阻止表被删除或截断)。
这不完全是读取锁 - 其他会话仍然可以查询表,包括锁定的行,只要它们没有for update
子句。但只要你所有的回调都做同样的事情,他们就应该按你的意愿行事。
答案 1 :(得分:1)
我认为您正在寻找Select For Update Cursor。 第一个读者将阻止其他读者(如果包含NOWAIT子句,则其他会话将不会等待)