Postgresql -> 来自简单更新的死锁。我找不到原因

标签 postgresql deadlock database-deadlocks

这是表格(简化):

                                       Table "public.link"
    Column     |            Type             |                     Modifiers                     
---------------+-----------------------------+---------------------------------------------------
 id            | integer                     | not null default nextval('link_id_seq'::regclass)
 page_id       | integer                     | 
 placed_at     | timestamp without time zone | default now()
Indexes:
    "link_pkey" PRIMARY KEY, btree (id)
    "link_page_id_index" btree (page_id)
Foreign-key constraints:
    "link_page_id_foreign_key" FOREIGN KEY (page_id) REFERENCES page(id) ON UPDATE RESTRICT ON DELETE RESTRICT

这里是查询(简化):

UPDATE link SET page_id = ?, placed_at = now() 
WHERE id IN ( SELECT id FROM link ... ) AND page_id IS NOT NULL

死锁消息:

ERROR: deadlock detected
  Detail: Process 5822 waits for ShareLock on transaction 19705; blocked by process 5821.
Process 5821 waits for ShareLock on transaction 19706; blocked by process 5822.
  Hint: See server log for query details.

由多个进程并行执行的查询如何导致死锁?
谢谢!

最佳答案

session A 尝试更新 ID 10、2、30、4, session B 尝试更新 ID 40、30、20、10

他们都尝试锁定各自的行以准备更新,A 获得 10 并等待 30,而 B 获得 30 并等待 10。死锁。

您的根本问题是您正在尝试更新并发事务中的(部分)相同 ID。

如果不了解您的数据库结构以及您正在尝试做什么,就很难提出最佳解决方案。通常,您要么确保不同的后端不会更新相同的行,要么减少超时并在随机暂停后重试。

关于Postgresql -> 来自简单更新的死锁。我找不到原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12856192/

相关文章:

database - "wait-die"和 "wound-wait"死锁预防算法有什么区别?

mysql - Laravel - 数据库事务 - 超出锁定等待超时

spring - Spring事务中发生死锁时调度程序停止

mysql - 如何根据 bool 值对同一字段进行两次计数?

php - 使用 PDO 准备好插入后获取最后一个插入 ID

linux - Red Hat Enterprise 5.9 上的 PostgreSQL 从 9.1 升级到 9.3

ruby - postgres 本地主机连接不良

c++ - 死锁C++线程条件变量

c# - 为什么 ASP.NET Core Web API 中没有出现这种死锁?

c# - 死锁 : Insert into a filetable statements appears to block one another