【发布时间】:2021-07-14 18:30:42
【问题描述】:
我想知道当两个事务并行执行SELECT ... FOR UPDATE 查询时会发生什么。背景是我想用SELECT ... FOR UPDATE和SKIP LOCKED实现一个作业队列,如下图:https://vladmihalcea.com/database-job-queue-skip-locked/。但在本文中,查询非常琐碎。
有两个事务 T1 和 T2 的示例(事务隔离级别设置为 READ_COMMITTED):
- T1 开始
- T1 执行
SELECT ... FOR UPDATE,搜索新行,这需要一些时间。 - T2 开始
- T2 使用与 T1 相同的 WHERE 子句和参数执行
SELECT ... FOR UPDATE,这也需要一些时间。 - T1 终于找到所有行,锁定它们
- T1 开始更新行(例如,将它们标记为现在为 IN_PROGRESS)
- T2 终于找到行 => 现在会发生什么?
一些问题:
- 我假设 T1 在原子操作中锁定行。这是正确的吗?
- 那么,当 T2 最终找到它的结果集并尝试锁定它无法做到的行时?在这种情况下,T2 如何反应?我的假设是它会等到 T1 释放锁(当不使用 NOWAIT 时)。
- 如果 T2 在 T1 进行任何更改(例如,将作业状态从 NEW 更改为 IN_PROGRESS)之前完成查询怎么办?两个事务能否找到相同的结果集?
- 如果 T1 以某种方式标记锁定的行(例如,通过将状态列从 NEW 更改为 IN_PROGRESS)并且 T2 查找原始状态 (NEW),那么 T2 是否会使用
SKIP LOCKED跳过标记的行? T2 会在 T1 进行更改后重新评估其结果集吗?
【问题讨论】:
标签: postgresql concurrency transactions select-for-update