The*_*ind 6 postgresql deadlock locking postgresql-9.3
我正在使用 Postgres 9.3。
我有 2 个表 :authn_session
和customer
. 每个都authn_session
属于 a customer
(因此有 acustomer_id
作为列,这是客户的 FK id
)。
注意:这些表包含对其他表和索引的额外 FK 引用。
现在,我开始 2 个不同的事务,它们按照下面提到的顺序执行以下操作:
发送:1
BEGIN;
UPDATE customer
SET customer__created_by =
(case when customer__created_by = 1 then 5
else customer__created_by end),
customer__modified_by =
(case when customer__modified_by = 1 then 5
else customer__modified_by end);
UPDATE authn_session
SET authn_session__created_by =
(case when authn_session__created_by = 1 then 5
else authn_session__created_by end),
authn_session__modified_by =
(case when authn_session__modified_by = 1 then 5
else authn_session__modified_by end);
Run Code Online (Sandbox Code Playgroud)
发送:2
BEGIN;
DELETE FROM authn_session
WHERE authn_session__guid IN ('abc3344-ab12-4444-9fdd-f4c5a6f7f210');
DELETE FROM customer
WHERE customer__id != 0
AND customer__id = 3
AND customer__name = 'C2'
AND customer__domain_name = 'a2.com';
Run Code Online (Sandbox Code Playgroud)
现在,当我使用下面提到的查询查看锁时,我对某一行感兴趣:
locktype | relation |mode |tid| vtid| pid | granted
tuple | authn_session|AccessExclusiveLock | | 11/5| 47894| TRUE
Run Code Online (Sandbox Code Playgroud)
询问 :
SELECT locktype, relation::regclass, mode, transactionid AS tid,
virtualtransaction AS vtid, pid, granted
FROM pg_catalog.pg_locks l LEFT JOIN pg_catalog.pg_database db
ON db.oid = l.database WHERE (db.datname = 'mY-db' OR db.datname IS NULL)
AND NOT pid = pg_backend_pid();
Run Code Online (Sandbox Code Playgroud)
现在,根据postgres 文档AccessExclusiveLocks 仅在以下情况下授予:
由 ALTER TABLE、DROP TABLE、TRUNCATE、REINDEX、CLUSTER、VACUUM FULL 和 REFRESH MATERIALIZED VIEW(无 CONCURRENTLY)命令获取。这也是未明确指定模式的 LOCK TABLE 语句的默认锁定模式。
我没有明确地做任何这些事情。那么为什么我的第二个进程(运行第二个事务 - 我检查了它在 DB 中的值)获得 AccessExclusiveLock ?为什么 pg_activities_blocked 视图说第二个进程(Delete)被第一个(UPDATE)阻塞?
顺便说一句,同时运行这两个查询的结果(一次来自每个查询的一个语句)会导致死锁。我是否遗漏了可能导致第二个进程在元组上获得 AccessExclusiveLock 的任何内容?
您引用的是手册的错误部分。该段落来自表级锁部分。您感兴趣的锁类型指定为tuple
。这意味着您需要参考手册的 Row-level Locks 部分以了解何时获得了这种锁。
除了表级锁,还有行级锁,可以是排他锁或共享锁。更新或删除特定行时,会自动获取对特定行的排他行级锁。锁一直保持到事务提交或回滚,就像表级锁一样。行级锁不影响数据查询;他们只阻止作者到同一行。
因此,锁可以由 Tx 1 或 Tx 2 获取,因为一个是更新行,另一个是删除行。
此外,正如ypercube所指出的那样??在注释中,您的更新语句不受过滤器的限制,因此每个语句都在整个表上运行。当与删除并行运行时,即使是过滤的删除,这样的更新自然会导致获取排他锁的冲突。
归档时间: |
|
查看次数: |
611 次 |
最近记录: |