From: | Peter Schindler <pschindler(at)synchronicity(dot)com> |
---|---|
To: | pg-hackers <pgsql-hackers(at)postgresql(dot)org> |
Subject: | RI_FKey_check: foreign key constraint blocks parallel independent inserts |
Date: | 2002-11-13 21:03:58 |
Message-ID: | 3DD2BE3E.DF1FD7E9@synchronicity.com |
Views: | Raw Message | Whole Thread | Download mbox | Resend email |
Thread: | |
Lists: | pgsql-general pgsql-hackers |
I've got a question about the foreign key constraint behavior.
It looks to me that inserts within transactions into a child table, which have the same FK value back to the parent will block until the first txn will commit or rollback. (see example below)
This seems to be based on the fact that the RI_FKey_check function will lock the parent row for update, so any other child row referring the same row will be locked out.
I've added a debug stmt into the RI_FKey_check function to see the query it does:
NOTICE: RI_FKey_check: PLAN2: SELECT 1 FROM ONLY "public"."parent" x WHERE "id" = $1 FOR UPDATE OF x
I think I basically understand, why this is done. To make sure that the parent row can't be deleted before the child row is committed and there would have an orphan reference.
But, if a lot of inserts happens into the child table and there is a mix of short and long running transactions, the likelihood of blocking is very high, even the inserts are independent and everything is ok (prim. key etc.). This is even more extreme, the smaller parent table is.
FYI, I've tried the same with Oracle and there is no such problem. The insert in the second session will come back immediately without blocking, though it will still maintain the integrity from other txns.
I wonder if there is a lower level way to maintain the locking and having the same behavior as oracle.
So, instead of using a "SELECT ... FOR UPDATE", using some pg function to lock a row with a different mode?
Overall, I find this restriction pretty bad and renders the use of foreign key constraints almost useless from the performance point of view as that leads to real serialization of transaction, even they don't have any overlaps.
in session1:
============
drop table child;
drop table parent;
create table parent (id integer not null);
ALTER TABLE parent ADD CONSTRAINT parent_PK PRIMARY KEY(ID);
create table child (id integer not null, parent_id integer not null);
ALTER TABLE child ADD CONSTRAINT child_PK PRIMARY KEY(ID);
ALTER TABLE child ADD CONSTRAINT child_parent_id FOREIGN KEY (parent_id) REFERENCES parent (ID);
insert into parent values (1);
insert into parent values (2);
begin;
insert into child values (1,1);
<this will be ok>
in session2 after the last insert in session1:
==============================================
begin;
insert into child values (2,1);
<this will block now until the session1 does commit or rollback>
--
Best regards,
Peter Schindler
From | Date | Subject | |
---|---|---|---|
Next Message | Stephan Szabo | 2002-11-13 22:22:51 | Re: RI_FKey_check: foreign key constraint blocks parallel |
Previous Message | Cédric Dufour (Cogito Ergo Soft) | 2002-11-13 20:36:13 | Re: readline help |
From | Date | Subject | |
---|---|---|---|
Next Message | Stephan Szabo | 2002-11-13 22:22:51 | Re: RI_FKey_check: foreign key constraint blocks parallel |
Previous Message | Rod Taylor | 2002-11-13 19:53:28 | Re: pg_dump in 7.4 |