有没有办法在Postgresql中选择未锁定的行?我有一个多线程应用程序将执行:
Select... order by id desc limit 1 for update
Run Code Online (Sandbox Code Playgroud)
在桌子上.
如果多个线程运行此查询,它们都会尝试拉回同一行.
一个获取行锁,另一个获取然后在第一个更新行后失败.我真正喜欢的是第二个线程获取匹配该WHERE子句的第一行并且尚未锁定.
为了澄清,我希望每个线程在执行select之后立即更新第一个可用行.
因此,如果有行ID: 1,2,3,4,第一个线程将进入,选择行ID=4并立即更新它.
如果在该事务期间第二个线程出现,我希望它能获得行ID=3并立即更新该行.
对于Share,也不会完成此操作,nowait因为该WHERE子句将与锁定的行匹配(ID=4 in my example).基本上我喜欢的是这个WHERE条款中的"并没有锁定" .
Users
-----------------------------------------
ID | Name | flags
-----------------------------------------
1 | bob | 0
2 | fred | 1
3 | tom | 0
4 | ed | 0
Run Code Online (Sandbox Code Playgroud)
如果查询是" Select ID from users where flags = 0 order by ID desc limit …
我有一个典型的生产者 - 消费者问题:
多个生产者应用程序将作业请求写入PostgreSQL数据库上的作业表.
作业请求的状态字段在创建时包含QUEUED.
有多个由当生产者插入一条新记录的规则通知的消费应用:
CREATE OR REPLACE RULE "jobrecord.added" AS
ON INSERT TO jobrecord DO
NOTIFY "jobrecordAdded";
Run Code Online (Sandbox Code Playgroud)
他们将尝试通过将其状态设置为RESERVED来保留新记录.当然,只有消费者才能成功.所有其他消费者不应该保留相同的记录.他们应该保留state = QUEUED的其他记录.
示例:某个生产者将以下记录添加到表jobrecord:
id state owner payload
------------------------
1 QUEUED null <data>
2 QUEUED null <data>
3 QUEUED null <data>
4 QUEUED null <data>
Run Code Online (Sandbox Code Playgroud)
现在,两个消费者A,B想要处理它们.他们同时开始跑步.一个应该保留id 1,另一个应该保留id 2,然后完成的第一个应该保留id 3等等.
在纯多线程世界中,我会使用互斥锁来控制对作业队列的访问,但消费者是可以在不同机器上运行的不同进程.它们只访问同一个数据库,因此所有同步都必须通过数据库进行.
我在PostgreSQL中阅读了很多关于并发访问和锁定的文档,例如http://www.postgresql.org/docs/9.0/interactive/explicit-locking.html 选择Postgresql PostgreSQL中的解锁行并锁定
从这些主题中我了解到,以下SQL语句应该能够满足我的需求:
UPDATE jobrecord
SET owner= :owner, state = :reserved
WHERE id = (
SELECT id from jobrecord …Run Code Online (Sandbox Code Playgroud) 我想一气呵成:
SELECT * FROM jobs WHERE status='PENDING';
UPDATE jobs SET status='RUNNING' WHERE status='PENDING';
Run Code Online (Sandbox Code Playgroud)
因此,获取所有待处理的作业,然后立即将它们设置为"RUNNING".
我不希望在两个语句中一个接一个地执行此操作的原因是作业可以在SELECT之后但在UPDATE之前作为'PENDING'添加到作业表中,因此我最终将作业设置为RUNNING,即使当它处于PENDING状态时,我没有抓住它.
反正有没有一个人这样做?所以我希望SELECT和UPDATE的结果在运行中发生.
谢谢.