因此,鉴于此交易:
select * from table_a where field_a = 'A' for update;
假设这给出了多行/结果,数据库会立即锁定所有结果吗?或者它会一次锁定一排。
如果后者为真,这是否意味着同时运行此查询会导致死锁?
因此,需要添加一个 order by 来保持订单的一致性来解决这个问题吗?
因此,鉴于此交易:
select * from table_a where field_a = 'A' for update;
假设这给出了多行/结果,数据库会立即锁定所有结果吗?或者它会一次锁定一排。
如果后者为真,这是否意味着同时运行此查询会导致死锁?
因此,需要添加一个 order by 来保持订单的一致性来解决这个问题吗?
该文档解释了发生的情况如下:
更新
FOR UPDATE
导致SELECT
语句检索到的行被锁定,就像更新一样。这可以防止它们被其他事务锁定、修改或删除,直到当前事务结束。也就是说,其他尝试UPDATE
,DELETE
,SELECT FOR UPDATE
, 或这些行的事务将被阻塞SELECT FOR NO KEY UPDATE
,直到当前事务结束;相反,将等待已在同一行上运行任何这些命令的并发事务,然后将锁定并返回更新的行(或没有行,如果该行已被删除)。但是,在or 事务中,如果要锁定的行在事务开始后发生了更改,则会引发错误。有关进一步的讨论,请参见第 13.4 节。SELECT FOR SHARE
SELECT FOR KEY SHARE
SELECT FOR UPDATE
REPEATABLE READ
SERIALIZABLE
您的问题的直接答案是 Postgres 不能“立即”锁定所有行;它必须首先找到它们。请记住,这是行级锁定而不是表级锁定。
该文档包括此说明:
SELECT FOR UPDATE
修改选定的行以将它们标记为锁定,因此将导致磁盘写入。
我将其解释为 Postgres 执行SELECT
查询并在找到行时将它们标记为已锁定。当 Postgres 识别该行时,锁(对于给定的行)开始。它一直持续到交易结束。
基于此,我认为使用SELECT FOR UPDATE
.