同一表上的两个"SELECT FOR UPDATE"语句会导致死锁吗?



假设两个同时发生的事务在Postgresql DB上执行以下查询:

交易 A:

SELECT * FROM mytable WHERE id IN (1, 2, 3, 4) FOR UPDATE

交易B:

SELECT * FROM mytable WHERE id IN (6, 3, 2, 1) FOR UPDATE

由于 Postgresql 以不一致的顺序获取行锁,是否有可能发生死锁? 例如,如果 Postgresql 要按照本例中给出 id 的顺序获取行锁,则存在死锁的可能性。

或者 Postgresql 内部是否足够智能,可以始终以同一表上的同时、离散SELECT FOR UPDATE语句不会相互死锁的方式获取行锁(例如,通过始终按主键顺序获取行锁)?

如果 Postgresql 没有自动防止此类死锁的发生,有没有办法修改查询以防止这种情况发生(例如,如果实际上 Postgresql 按照给出 id 的顺序获取行锁,那么对 id 进行一致排序应该可以防止死锁)?

感谢您的任何帮助!

对不起,我有另一个答案,但它是错误的。

文档指出,ORDER BY 子句在 FOR UPDATE 子句之前应用。因此,锁是以选择行的任何顺序获取的(我已经通过测试确认了这一点)。如果需要按其他顺序选择它们,可以使用:

SELECT * FROM (SELECT * FROM table ORDER BY id FOR UPDATE) ORDER BY another_column;

你可能想在PostgreSQL邮件列表中尝试你的问题。

从 http://www.postgresql.org/docs/9.1/static/explicit-locking.html:

PostgreSQL 会自动检测死锁情况,并通过中止其中一个涉及的事务来解决它们

该页面使用了一个涉及UPDATEs 的示例,这些示例等效于锁定方面的SELECT ... FOR UPDATE

最新更新