如何锁定行进行更新而不通过连接返回数据?

Joh*_*hir 3 postgresql locking update

我想做这样的事情:

begin;
select * from foos where owner_id=123 and unread=true order by id for update;
update foos set unread=false where owner_id=123 and unread=true;
commit;
Run Code Online (Sandbox Code Playgroud)

目标是避免两个进程同时执行 UPDATE 时出现死锁。此处详细描述了问题:Why am I get a deadlock for a single UPDATE query?

在我获取锁的语句中,我不需要有关行的任何信息。我只想锁定那些特定的行。有没有办法做到这一点(优雅或hacky),告诉postgres不要做任何实际给我数据的工作?

Erw*_*ter 5

关于避免死锁的目标:请参阅我对相关问题的回答:

关于标题中的问题:

在子查询中使用带有锁定子句的SELECT空(最短、最便宜)列表,并在外部运行:count()SELECT

SELECT count(*) AS locked_rows
FROM  (
   SELECT FROM foos
   WHERE  owner_id = 123
   AND    unread
   ORDER  BY id
   FOR    UPDATE  -- !
   ) sub;
Run Code Online (Sandbox Code Playgroud)

通过这种方式,您可以获得包含锁定行数的单个结果行。在事务期间,子查询中选择的所有行都将被锁定。(如果有0行,您可以中止。)

旁白:

  • and unread=true只是一种吵闹的说法AND unread
  • 如果unread可以的话NULL,考虑unread IS NOT TRUE一下。