Re: Foreign Keys and Deadlocks

From: David Kerr <dmk(at)mr-paradox(dot)net>
To: pgsql-general(at)postgresql(dot)org
Subject: Re: Foreign Keys and Deadlocks
Date: 2011-11-04 16:01:29
Message-ID: 20111104160129.GA76283@mr-paradox.net
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-general

On Thu, Nov 03, 2011 at 03:30:20PM -0700, David Kerr wrote:
- Howdy,
-
- We have a process that's deadlocking frequently. It's basically multiple threads inserting data into a single table.
-
- That table has FK constraints to 3 other tables.
-
- I understand how an FK check will cause a sharelock to be acquired on the reference table and in some instances that
- leads to or at least participates in a deadlock.
-
- I don't think that's the case here, (or at least not the entire case) but I could use some assistance in helping
- to convince my developers of that ;). They'd like to just remove the FK and be done with it.

[snip]

So it appears that I'm the big dummy, and that you can deadlock with just inserts.

I did more digging and found some good discussions on the subject in general, but
most of the examples out there contain explicit updates (which is why i was confused)
but it looks like it's being addressed.

http://justatheory.com/computers/databases/postgresql/fk-locks-project.html
http://www.mail-archive.com/pgsql-hackers(at)postgresql(dot)org/msg158205.html
http://www.commandprompt.com/blogs/alvaro_herrera/2010/11/fixing_foreign_key_deadlocks/

Attached is the script to reproduce it with only inserts (for postarities sake)

drop table a;
drop table b;
drop table c;
drop table d;

create table b ( bref int, description text);
alter table b add primary key (bref);

create table c ( cref int, description text);
alter table c add primary key (cref);

create table d ( dref int, description text);
alter table d add primary key (dref);

create table a ( bref int, cref int, dref int, description text);
alter table a add primary key (bref, cref);
alter table a add foreign key (bref) REFERENCES b(bref);
alter table a add foreign key (cref) REFERENCES c(cref);
alter table a add foreign key (dref) REFERENCES d(dref);

insert into b values (1,'hello');
insert into b values (2,'hello2');
insert into b values (3,'hello3');
insert into b values (4,'hello4');

insert into c values (1,'hello');
insert into c values (2,'hello2');
insert into c values (3,'hello3');
insert into c values (4,'hello4');

insert into d values (1,'hello');
insert into d values (2,'hello2');
insert into d values (3,'hello3');
insert into d values (4,'hello4');

Fire up 2 psqls
#SESSION1
## STEP1
begin;
insert into a values (1,1,1,'hello');
##STEP3
insert into a values (1,2,1,'hello2');

#SESSION2
## STEP2
begin;
insert into a values (1,2,1,'hello2');
## STEP4
insert into a values (1,1,1,'hello');

You'll get:
ERROR: deadlock detected
DETAIL: Process 8382 waits for ShareLock on transaction 7222455; blocked by process 6981.
Process 6981 waits for ShareLock on transaction 7222456; blocked by process 8382.
HINT: See server log for query details

In response to

Responses

Browse pgsql-general by date

  From Date Subject
Next Message Scott Marlowe 2011-11-04 16:11:32 Re: Replication Across Two Servers?
Previous Message Carlos Mennens 2011-11-04 15:59:01 Re: Replication Across Two Servers?