这在PostgreSQL 9.4.1中发生。
我有两个表针对这个问题进行了简化。
core_deck
+-------------+--------------------------+-----------------------------------------------------------+
| Column | Type | Modifiers |
|-------------+--------------------------+-----------------------------------------------------------|
| id | integer | not null default nextval('core_deck_id_seq'::regclass) |
| status | character varying(32) | not null |
| account_id | integer | not null |
+-------------+--------------------------+-----------------------------------------------------------+
core_membership
+----------------+-----------------------+-----------------------------------------------------------------
| Column | Type | Modifiers
|----------------+-----------------------+-----------------------------------------------------------------
| id | integer | not null default nextval('core_membership_id_seq'::regclass)
| account_id | integer | not null
| visit_count | smallint | not null
+----------------+-----------------------+-----------------------------------------------------------------
每个表都有一个core_account
表的外键。
我看到这样的死锁:
Process 43189 waits for ShareLock on transaction 2929976445; blocked by process 3982.
Process 3982 waits for ShareLock on transaction 2929976441; blocked by process 43189.
Process 43189: UPDATE "core_deck" SET "account_id" = 10094676, "status" = 'COMPLETED' WHERE "core_deck"."id" = 10563730
Process 3982: UPDATE "core_membership" SET "account_id" = 10094676, "visit_count" = 9 WHERE "core_membership"."id" = 13537206
我不明白为什么会发生这种情况,因为外键没有被更改,并且帐户表中没有任何内容正在更新。
我们将不胜感激。
更新07-18 :上面的SQL显示外键设置为它已经存在的相同值。这是因为Django在更新期间显然设置了所有值,而不仅仅是正在更改的值。
更新07-19 :这是基于我昨天给出的答案的另一个例子。如图所示我很遗憾无法重现此锁定问题
create table parent (id int PRIMARY key);
create table child_1 (id int primary key, parent_id int references parent, name varchar(32));
create table child_2 (id int primary key, parent_id int references parent, name varchar(32));
create view pg_my_locks as select relname, mode from pg_locks l join pg_class c on l.relation = c.oid where relname not like 'pg\_%';
begin;
update child_1 set parent_id = 1, name = 'Foo' where id = 1
update child_2 set parent_id = 1, name = 'Bar' where id = 1
select * from pg_my_locks
+--------------+------------------+
| relname | mode |
|--------------+------------------|
| child_2_pkey | RowExclusiveLock |
| child_2 | RowExclusiveLock |
| child_1_pkey | RowExclusiveLock |
| child_1 | RowExclusiveLock |
+--------------+------------------+
end;