为什么不同表上的这两个更新会导致死锁?

时间:2016-07-18 23:44:40

标签: postgresql

这在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;

0 个答案:

没有答案