【问题标题】:Postgres : ShareLock Deadlock on transactionPostgres:事务上的ShareLock死锁
【发布时间】:2020-03-19 20:56:49
【问题描述】:

最近我们开始在日志中发现很多死锁错误。 (Postgres 服务器 9.6.5)

我们的表由两列组成,一列是自增主键,另一列是 json 对象。 json 对象的两个属性被定义为 unique 。 现在在日志中,我们不断收到错误,表明不同行上的两个简单插入查询相互阻塞。

============

process 65325 detected deadlock while waiting for ShareLock on transaction 2934224126 after 1000.050 ms

DETAIL:  Process holding the lock: 35530. Wait queue: .

CONTEXT:  while inserting index tuple (128,10) in relation "A"

STATEMENT:  INSERT INTO A AS t (info) VALUES('{"x":"y",....)

ERROR:  deadlock detected

DETAIL:  Process 65325 waits for ShareLock on transaction 2934224126; blocked by process 35530.

Process 35530 waits for ShareLock on transaction 2934224125; blocked by process 65325.

Process 65325: INSERT INTO A AS t (info) VALUES({"x":"y",....)

Process 35530: INSERT INTO A AS t (info) VALUES({"x":"z",....)

=====================

所以基本上两个不同的行处于死锁状态。 对于这种死锁可能发生的情况有什么建议吗?

【问题讨论】:

  • 在您的过时版本 9.6.5 和当前版本 9.6.16 之间有几个与“虚假死锁”相关的错误修正。 why-upgrade.depesz.com/…

标签: postgresql deadlock


【解决方案1】:

行永远不会陷入僵局。陷入死锁的不是两个不同的行,而是两个不同的事务。您的日志向您显示每个事务的最近插入尝试。据推测,每个事务中也有先前的插入。但这些不会出现在日志中,除非它们出于其他原因(如 log_statement=all)而出现。

因此,如果 T1 成功(并且不可见地查看您的日志文件)插入“x”:“y”,则 T2 成功且不可见地插入“x”:“z”,现在 T1 尝试插入“x”: "z" 和 T2 尝试 "x":"y",就会出现死锁。假设唯一索引在 info->>'x'

如果您不使用 JSON,这将是同样的问题。

缓解措施是,不要在每个事务中插入超过一行。或者,如果您这样做,请始终以指定的顺序插入它们(例如,由于拉丁字母顺序,“y”在“z”之前),尽管在这种情况下,您只需将死锁错误替换为唯一键违规。或者,只是准备好抓住僵局并重试。

【讨论】:

  • 谢谢,尽管由于明确提及与唯一约束不冲突的查询,日志记录似乎令人困惑。我将尝试实施您的缓解建议。
  • @varun 日志中提到的语句是冲突的一部分,它们并不是全部。 PostgreSQL 不保留当前事务中先前执行的语句的内存,因此无法报告它们。 (也许应该教它用历史语句保留一个有限大小的缓冲区)
  • 是的,如果我们也有历史陈述,那么僵局的理解就会变得明显。再次感谢!
  • 赞成,因为这个提示有助于解决我遇到的死锁问题,即多个服务器将数据写入同一个表,即使每组行对服务器来说都是唯一的。只需对行进行排序即可解决问题。谢谢@jjanes
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-03-04
  • 1970-01-01
  • 1970-01-01
  • 2014-04-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多