13

假设两个并发事务在 Postgresql DB 上执行以下查询:

交易A:

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

交易乙:

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

由于 Postgresql 以不一致的顺序获取行锁,是否可能发生死锁?例如,如果 Postgresql 以本例中给出的 id 顺序获取行锁,那么就有可能发生死锁。

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

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

谢谢你的帮助!

4

2 回答 2

3

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

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

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

您可能想在 PostgreSQL邮件列表上尝试您的问题。

于 2012-10-10T19:52:03.493 回答
0

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

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

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

于 2012-10-10T19:51:22.927 回答