gpt4 book ai didi

postgresql - Postgres 9.4 在单个表上读取-修改-写入时检测到死锁

转载 作者:行者123 更新时间:2023-11-29 12:42:54 25 4
gpt4 key购买 nike

我们有一个带有简单表格的应用程序

given_entity{
UUID id;
TimeStamp due_time;
TimeStamp process_time;
}

这是一个 spring boot (1.2.5.RELEASE) 应用程序,它使用 spring-data-jpa.1.2.5.RELEASE 和 hibernate-4.3.10.FINAL 作为 jpa provier。
我们有这个应用程序的 5 个实例,每个实例都有一个每 2 秒运行一次的调度程序,并在数据库中查询截止日期为最后 2 分钟但尚未处理的行;

SELECT * FROM given_entity 
WHERE process_time is null and due_time between now() and NOW() - INTERVAL '2 minutes'
FOR UPDATE

要求是上表的每一行都被恰好一个应用程序实例成功处理。然后应用程序实例处理这些行并在一个事务中更新其 process_time 字段。这可能会或可能不会超过 2 秒,这是调度程序间隔。此外,我们在这张表上没有任何索引,只有 PK 索引。第二点值得注意的是,这些实例可能会在这个表中插入行,该表由客户端单独调用。

问题:在日志中我看到了来自 postgresql 的这条消息(很少但它发生了)

ERROR: deadlock detected
Detail: Process 10625 waits for ShareLock on transaction 25382449; blocked by process 10012.
Process 10012 waits for ShareLock on transaction 25382448; blocked by process 12238.
Process 12238 waits for AccessExclusiveLock on tuple (1371,45) of relation 19118 of database 19113; blocked by process 10625.
Hint: See server log for query details.
Where: while locking tuple (1371,45) in relation "given_entity"

问题: 这是怎么发生的? 我检查了 postgresql 锁并搜索了互联网。我没有发现任何说死锁只可能在一张简单的表上发生的事情。 我也无法使用测试重现此错误。

最佳答案

进程 A 尝试锁定第 1 行,然后锁定第 2 行。同时,进程 B 尝试锁定第 2 行,然后锁定第 1 行。这就是触发死锁所需的全部。

问题是行锁的获取顺序不确定,因为 SELECT 以不确定的顺序返回其行。避免这种情况只是确保所有进程在锁定行时就顺序达成一致的问题,即:

SELECT * FROM given_entity 
WHERE process_time is null and due_time between now() and NOW() - INTERVAL '2 minutes'
ORDER BY id
FOR UPDATE

在 Postgres 9.5+ 中,您可以使用 FOR UPDATE SKIP LOCKED 简单地忽略被另一个进程锁定的任何行。

关于postgresql - Postgres 9.4 在单个表上读取-修改-写入时检测到死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40083578/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com