有没有办法在 Postgresql 中选择未锁定的行?我有一个多线程应用程序可以执行以下操作:
Select... order by id desc limit 1 for update
在一张桌子上。
如果多个线程运行此查询,它们都会尝试拉回同一行。
一个获得行锁,另一个阻塞,然后在第一个更新行后失败。我真正想要的是让第二个线程获得与WHERE
子句匹配且尚未锁定的第一行。
为了澄清,我希望每个线程在选择后立即更新第一个可用行。
因此,如果有带有 的行ID: 1,2,3,4
,第一个线程会进来,选择带有 的行ID=4
并立即更新它。
如果在该事务期间出现第二个线程,我希望它获取行ID=3
并立即更新该行。
For Share 不会完成此操作,nowait
因为WHERE
子句将与锁定的行匹配(ID=4 in my example)
。基本上我想要的是WHERE
子句中的“AND NOT LOCKED”之类的东西。
Users
-----------------------------------------
ID | Name | flags
-----------------------------------------
1 | bob | 0
2 | fred | 1
3 | tom | 0
4 | ed | 0
如果查询是“ Select ID from users where flags = 0 order by ID desc limit 1
”并且当返回一行时,下一个是“ Update Users set flags = 1 where ID = 0
”,那么我希望第一个线程用 来抓取行,ID 4
下一个线程用 来抓取行ID 3
。
如果我将“”附加For Update
到选择,那么第一个线程获取该行,第二个线程阻塞然后什么都不返回,因为一旦第一个事务提交,该WHERE
子句就不再满足。
如果我不使用“ For Update
”,那么我需要在后续更新中添加一个 WHERE 子句(WHERE flags = 0),这样只有一个线程可以更新该行。
第二个线程将选择与第一个线程相同的行,但第二个线程的更新将失败。
无论哪种方式,第二个线程都无法获取行并更新,因为我无法让数据库将第 4 行提供给第一个线程,将第 3 行提供给第二个线程,事务重叠。