有没有一种方法可以在PostgreSQL中选择未锁定的行? 我有一个多线程应用程序将执行以下操作:
Select... order by id desc limit 1 for update
在一个表上执行此查询时,如果有多个线程运行,则它们都尝试获取同一行。
其中一个获取了行锁,另一个被阻塞,然后在第一个更新该行后失败。我真正想要的是第二个线程获取第一个匹配WHERE
子句且尚未锁定的行。
澄清一下,我希望每个线程在执行选择操作后立即更新第一行可用行。
因此,如果有ID为1、2、3、4的行,则第一个线程将进入,选择具有ID=4
的行并立即更新它。
如果在该事务期间出现第二个线程,则我希望它获取具有ID=3
的行并立即更新该行。
由于WHERE
子句会匹配已锁定的行(例如我的示例中的ID = 4)
,因此使用Share或nowait
将无法实现这一点。基本上,我想要的是在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,因为这些事务是重叠的。