首页 > 解决方案 > 简单更新时的死锁:ShareLock 和 AccessExclusiveLock

问题描述

我注意到错误日志中偶尔会出现死锁,原因是同一行的并行更新:

[1111]:LOG:  process 1111 detected deadlock while waiting for ShareLock on transaction 123456789 after 1000.095 ms
[1111]:DETAIL:  Process holding the lock: 2222. Wait queue: .
[1111]:CONTEXT:  while locking tuple (9999999,99) in relation "ccc"
[1111]:STATEMENT:  update ccc set modification_date_time=$1, ... where id=$7
[1111]:ERROR:  deadlock detected
[1111]:DETAIL:  Process 1111 waits for ShareLock on transaction 123456789; blocked by process 2222.
    Process 2222 waits for AccessExclusiveLock on tuple (9999999,99) of relation 55555 of database 66666; blocked by process 1111.
    Process 1111: update ccc set modification_date_time=$1, ... where id=$7
    Process 2222: update ccc set modification_date_time=$1, ... where id=$7
[1111]:HINT:  See server log for query details.

应用程序中发生的情况如下:

  1. Hibernate 加载实体(行)
  2. 正在修改字段
  3. Hibernate将实体保存到数据库,产生UPDATE语句

目前尚不清楚为什么会发生这种情况,因为这只是一次正常的更新,进程不应相互依赖。我知道这是一个竞争条件,但从应用程序的角度来看,这并不重要。

我不完全理解,什么是ShareLockand AccessExclusiveLock,所以到目前为止我有两个想法:

标签: postgresqlhibernate

解决方案


发生死锁必须涉及多个锁定对象。

检查事务已更新了哪些其他行。如果您负担得起,也许您可​​以打开 SQL 日志记录。

死锁通常可以通过以某种特定顺序锁定行来避免,例如通过升序 ID。

缓慢的处理不会导致死锁,尽管长事务会增加危险。

如果死锁很少发生,不要担心它们。只需重试事务。


推荐阅读