这个问题可以被视为对我对Can two concurrent but identical DELETE statements cause a deadlock?的评论的后续行动。
我想知道在以下语句中行是否以my_status
的顺序锁定:
SELECT 1 FROM my_table ORDER BY my_status FOR UPDATE;
在https://www.postgresql.org/docs/9.5/static/sql-select.html上有一个有趣的说法:
在事务隔离级别
SELECT
上运行并使用READ COMMITTED
和锁定子句的ORDER BY
命令可能会无序返回行。这是因为首先应用ORDER BY
。该命令对结果进行排序,但随后可能会阻止尝试获得对一个或多个行的锁定。SELECT
解除阻塞后,某些排序列值可能已被修改,从而导致这些行似乎是乱序的(尽管就原始列值而言,它们是有序的)。可以通过在子查询中放置FOR UPDATE
/SHARE
子句来解决此问题,例如SELECT * FROM (SELECT * FROM mytable FOR UPDATE) ss ORDER BY column1;
我不确定是否能回答我的问题。这说明,首先应用ORDER BY
,并且需要将FOR UPDATE
放在子查询中,以解决如果order列的值实际输出顺序可能不同的副作用在此期间已更改。换句话说,将FOR UPDATE
放在子查询中可确保在订购之前进行锁定。
但这并不能真正告诉我们行是否实际上按照ORDER BY
子句确定的顺序锁定了?
答案 0 :(得分:2)
按ORDER BY
子句的顺序锁定行,就像扫描表时一样。
执行查询并对行进行排序,然后PostgreSQL依次锁定行。本质上,ORDER BY
发生在FOR UPDATE
之前。
现在,由于并发事务持有的锁,可能会锁定行阻塞。如果发生这种情况,并且我们处于READ COMMITTED
隔离级别,则PostgreSQL 等待,直到它获得锁并然后获取该行的当前版本,该行它会锁定。
如果并发事务修改了定义顺序的列,则最终结果将不符合ORDER BY
定义的顺序。