【发布时间】:2019-06-13 06:34:01
【问题描述】:
我注意到并发执行简单且相同的查询类似于
BEGIN;
SELECT files.data FROM files WHERE files.file_id = 123 LIMIT 1 FOR UPDATE;
UPDATE files SET ... WHERE files.file_id = 123;
COMMIT;
导致死锁,这让我感到惊讶,因为这样的查询看起来不应该造成死锁。另外:完成这样的请求通常只需要几毫秒。在这种死锁情况下,如果我运行:
SELECT blockeda.pid AS blocked_pid, blockeda.query as blocked_query,
blockinga.pid AS blocking_pid, blockinga.query as blocking_query FROM pg_catalog.pg_locks blockedl
JOIN pg_stat_activity blockeda ON blockedl.pid = blockeda.pid
JOIN pg_catalog.pg_locks blockingl ON(blockingl.transactionid=blockedl.transactionid
AND blockedl.pid != blockingl.pid)
JOIN pg_stat_activity blockinga ON blockingl.pid = blockinga.pid
WHERE NOT blockedl.granted;
在整个死锁期间,我看到为 blocked_pid 和 blockin_pid 列出了两个相同的选择语句。
所以我的问题是:尝试选择同一行FOR UPDATE 导致死锁的查询是否正常和预期?如果是这样,在这种情况下避免死锁的最佳策略是什么?
【问题讨论】:
-
可以发
CREATE TABLE files吗? -
这样的问题需要准确的表定义和 Postgres 版本。
标签: sql postgresql concurrency sql-update deadlock