在我们的一个java应用程序(基于postgresql db)中,我们有一个数据库表,用于维护要执行的任务列表。 每行都有一个json blob,用于任务的详细信息以及预定的时间值。
我们有一些java工作者/线程,其工作是搜索准备执行的任务(基于其计划值),从表中执行和删除它们。执行任务可能需要几秒钟。
问题是,多个工作人员可能会占用同一行,从而导致重复执行任务,这是我们想要避免的。
一种方法是,在执行select
抓取一行时,使用FOR UPDATE
执行此操作以锁定该行,从而阻止其他工作人员抓住锁定的同一行。
我对这种方法的关注是,只有在db中执行select
事务时才会锁定行(根据this),而java代码实际上是在执行行/任务选择了,锁定已经消失,另一个工人可以再次抓住它。
有些人可以了解上述方法是否可行吗?谢谢!
答案 0 :(得分:0)
将DB调用视为原子指令并在表周围设计无锁算法,使用更新将“正在进行”的布尔列从false更改为true。也可能只是state int
(0 =有效,1 =进行中,N =结果代码)。
确保您在状态0上有一个部分索引(可能还有1个从崩溃中恢复以查找正在进行的任务),因此...where state=0
仍然具有选择性和快速性(在预定的时间索引之上) )。
希望这有帮助。
答案 1 :(得分:0)
当一个线程成功锁定给定连接上的行时,另一个尝试获取另一个连接上的行的锁定应该失败。您应该使用某种 no-wait 子句发出select-for-update,以便在行被锁定时立即请求失败。
现在,这不能解决查询vs锁定竞争,因为失败的锁定可能会中断线程的执行。您可以通过(在每次执行中)解决这个问题: