1

最近,我们遇到了一个死锁问题。我们系统的两个部分将在相似的时间更新同一个表,一个更新(命名为“UP1”)事务中的几行,另一个(命名为“UP2”)使用类似“update ... where id”的 sql在 (...)”。

似乎是因为 sql "update ... where id in (...)" 中的 id 乱序,例如 "5,6,2,3,4,1"; 并且在事务中,更新操作将按照“1,2,3,4,5,6”的顺序执行。当“UP1”更新id“1,2,3,4”,“UP2”更新id“5,6”时,“UP1”想要被“UP2”锁定的id 5,“UP2”想要被“UP1”锁定的id 2,所以死锁就出来了。

我的问题是,数据库是否会一一锁定行,只有在 sql 或事务完成时才释放它们?如果不是,为什么不能在事务开始时锁定所有行或“where id in (...)” sql,为什么不能一一释放更新的行?

期待任何有用的回复,谢谢。

4

1 回答 1

1

你几乎走在正确的轨道上。使用默认的Read Committed Isolation Level PostgreSQL 一路获取锁,并在事务提交或回滚时释放它们。

如果您可以确保所有 UPDATE 操作以相同的顺序更新行,您将永远不会遇到死锁。您是否尝试过UP1按升序更新行并以相同的方式对IN列表进行排序UP2

如果你不能保证同步更新,你可能会对Serializable Isolation Level感兴趣。它是最严格的隔离级别,可能会稍微减慢您的查询速度,尤其是在高并发的情况下。但它应该可以防止您看到的错误。此外,请准备好由于序列化失败而重试事务。

为此,请通过以下方式开始您的交易

BEGIN ISOLATION LEVEL SERIALIZABLE;
于 2012-07-12T19:30:29.273 回答