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

时间:2012-10-10 18:10:48

标签: postgresql rails-postgresql database-deadlocks

假设两个并发事务在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语句不会相互死锁(例如,总是按主键的顺序获取行锁)? / p>

如果Postgresql 不能自动防止此类死锁发生,是否有办法修改查询以防止出现这种情况(例如,事实上,如果事实上Postgresql按照id的顺序获取行锁给定,然后一致地排序id应该防止死锁)?

感谢您的帮助!

2 个答案:

答案 0 :(得分:3)

抱歉,我有另一个答案,但这是错误的。

文档说明在FOR UPDATE子句之前应用了ORDER BY子句。因此,无论以何种顺序选择行,都可以获取锁(我已经通过测试确认了这一点)。如果您需要以不同的顺序选择它们,可以使用:

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

您可能想在PostgreSQL mailing list上尝试您的问题。

答案 1 :(得分:0)

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

  

PostgreSQL会自动检测死锁情况并通过中止其中一个交易来解决它们

该页面使用了一个涉及UPDATE的示例,在锁定方面相当于SELECT ... FOR UPDATE