如何避免Postgres的死锁?

时间:2014-08-26 13:58:48

标签: postgresql concurrency deadlock database-deadlocks

我运行多个服务器,每个服务器都运行多个更新语句,例如这些

UPDATE user SET ... WHERE user_id = 2;
UPDATE user SET ... WHERE user_id = 1;
UPDATE user SET ... WHERE user_id = 3;

如果有像:

这样的同步更新
UPDATE user SET ... WHERE user_id = 1;
UPDATE user SET ... WHERE user_id = 2;

然后我会遇到错误deadlock detected

现在,我的修复方法是在客户端订购更新语句,并始终保证ID的顺序相同。即我总是在客户端ASC by user_id

上对语句进行排序

到目前为止,这似乎解决了这个问题,但我仍有疑问:

  1. 这是否(命令语句)是解决死锁错误的好方法?
  2. 如果我开始进行多表更新,我是否还必须在表中对语句进行排序?

1 个答案:

答案 0 :(得分:0)

在应用程序级别订购语句是一个很好的解决方案,因为它避免了数据库开销。这些陈述需要保持每个表的顺序。如果这在应用程序中很容易实现,那就值得。

在数据库级别还有一个解决方案:serializable isolation

  

Serializable隔离级别提供最严格的事务隔离。此级别模拟所有已提交事务的串行事务执行;好像交易是一个接一个地,连续地,而不是同时执行的。但是,与可重复读取级别一样,使用此级别的应用程序必须准备好因序列化失败而重试事务。实际上,此隔离级别与可重复读取完全相同,只是它监视可能使并发可序列化事务集的执行行为的方式与所有可能的串行(一次一个)执行这些事务的方式不一致。

您可以在启动交易时设置此隔离级别。这确实增加了一些数据库开销,但更重要的是,应用程序必须准备好捕获序列化失败并重试事务。