如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?

Posted

技术标签:

【中文标题】如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?【英文标题】:How can you use 'For update skip locked' in postgres without locking rows in all tables used in the query? 【发布时间】:2017-12-21 06:19:04 【问题描述】:

当您想使用 postgres 的 SELECT FOR UPDATE SKIP LOCKED 功能来确保两个不同的用户从表中读取并声明任务不会被彼此阻塞,也不会得到另一个用户已经在读取的任务:

查询中正在使用连接来检索任务。除了包含主要信息的表之外,我们不希望任何其他表具有行级锁定。下面的示例查询 - 仅锁定表中的行 - 以下查询中的“任务”

SELECT v.someid , v.info,  v.parentinfo_id, v.stage  FROM task v, parentinfo pi  WHERE v.stage = 'READY_TASK' 
             AND v.parentinfo_id = pi.id 
             AND pi.important_info_number = ( 
             SELECT MAX(important_info_number) FROM parentinfo )
              ORDER BY v.id limit 200 for update skip locked;

现在如果用户 A 正在检索该表的大约 200 行,用户 B 应该能够检索另一组 200 行。

编辑:根据下面的评论,查询将更改为:

SELECT v.someid , v.info,  v.parentinfo_id, v.stage  FROM task v, parentinfo pi  WHERE v.stage = 'READY_TASK' 
             AND v.parentinfo_id = pi.id 
             AND pi.important_info_number = ( 
             SELECT MAX(important_info_number) FROM parentinfo)  ORDER BY v.id limit 200 for update of v skip locked;

如何最好地按行排序?虽然如果多个用户调用此命令,该命令将生效,但仍应为返回的行保持一定的顺序神圣性。

此外,这是否也确保调用相同选择查询的多个线程将检索不同的行集,还是仅对更新命令进行锁定?

【问题讨论】:

Doc: "FOR lock_strength [ OF table_name [, ...] ] [ NOWAIT | SKIP LOCKED ] ... 如果在锁定子句中命名了特定表,则只有来自这些表的行被锁定;在 SELECT 中使用的任何其他表都被简单地读取为平常。” 【参考方案1】:

刚刚对此进行了一些试验 - 多个选择查询最终会检索不同的行集。并且order by保证了最终得到的结果的顺序。

【讨论】:

以上是关于如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 postgres 中使用 Pivot

如何在 Postgres 中使用 Plpython3 返回结果集

在 postgres 上将表导出到 csv

如何使用 Postgres 中 CSV 文件中的值更新选定的行?

Postgres - 冲突 - 如何知道是不是发生了更新而不是插入 [重复]

如何使用NodeJ从Postgres返回INSERT命令中的所有数据