我注意到错误日志中偶尔出现死锁,原因是同一行的并行更新:
[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.
申请中会发生以下情况:
UPDATE
语句目前尚不清楚它为什么会发生,因为它只是一次正常的更新,而且流程不应该相互依赖。我知道这是一种竞争条件,但从应用的角度来看,它并不重要。
我不完全明白,ShareLock
和AccessExclusiveLock
是什么,所以到目前为止我有2个想法:
答案 0 :(得分:1)
必须有多个锁定对象才能发生死锁。
检查事务已更新的其他行。如果你负担得起,也许你可以打开SQL日志。
通过按特定顺序锁定行,通常可以避免死锁,例如通过升序ID。
虽然长时间的交易增加了危险,但是处理速度慢不会造成死锁。
如果僵局很少发生,请不要担心它们。只需重试交易即可。