postgresql - Postgres : ShareLock Deadlock on transaction

标签 postgresql deadlock

最近我们开始在日志中收到很多死锁错误。 (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",....)

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

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

最佳答案

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

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

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

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

关于postgresql - Postgres : ShareLock Deadlock on transaction,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59017059/

相关文章:

sql - 具有两个参数的 PostgreSQL 中的间隔(天)

使用数组输入和数组输出为 PostgreSQL 创建简单的 C 函数

java - Lambda 表达式可以解决死锁吗?

mysql - golang中查询mysql时发生死锁错误,不是在查询段中而是在out of "rows.Next()"循环之后

json - postgres json_populate_recordset 没有按预期工作

sql - 有没有办法在 postgresql 中使用 qualify

mysql - 选择字段为非空的所有项目

multithreading - 在实时应用程序中检测死锁的方法

mysql - 共享锁升级为独占锁避免MySQL死锁

Java - 模拟3个线程之间的死锁并设置优先级