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