I'm trying to delete a table (called incoming
) in a busy database with 100s of transactions per second. The table itself is empty (performed a truncate table
before). If I try to do drop table incoming
a lot of transactions on various other tables are waiting for drop table
to finish – obviously not good.
I began deleting indexes, constrains and columns 1 by 1 to identify what is blocking the table deletion and got to a foreign key constraint that was causing the lock. Here's the 'final' incoming
table schema:
create table incoming
(
account_id integer
constraint incoming_account_id_fkey
references account
);
From the blocked queries (taking the ticket
table below as an example) it doesn't look like the account
table queries are blocked but the queries on ticket
– a busy table that has a foreign key to the account
table. Why would deleting a FK in incoming
block queries in ticket
?
Here's the outline again on the 3 tables:
incoming
– this is where the foreign key I want to delete lives (see schema below).account
– foreign key reference table.ticket
– busy table (select, insert, update, etc..) that has a foreign key constraint toaccount
.
What I tried doing:
I tried disabling the triggers on the table: ALTER TABLE incoming DISABLE TRIGGER ALL;
and making the FK DEFERRABLE: ALTER TABLE incoming ALTER CONSTRAINT incoming_account_id_fkey DEFERRABLE;
. Didn't help.
Here's the output of the pg_constraint
:
SELECT conname, conindid::regclass, confrelid::regclass, * FROM pg_constraint WHERE conrelid = 'incoming'::regclass
:
Best Answer
Foreign key constraints are implemented as system triggers in PostgreSQL.
This query shows you the triggers behind your foreign key constraint:
You see that two of these triggers are defined on the target table,
account
.If you drop table
incoming
, that will also drop the foreign key constraint and consequently drop the triggers onaccount
, which requires a shortACCESS EXCLUSIVE
lock onaccount
.That should not be disruptive, but it seems that you are running long transactions that involve
account
. Now theDROP TRIGGER
onaccount
has to queue behind the currently active transactions that hold locks onaccount
, and all later transactions have to queue behind theDROP TRIGGER
, which is what you observe.You will have to find a time when there are no long running transactions involving
account
, then yourDROP TABLE
will finish quickly without blocking other sessions.Side remark: choose
bigint
rather thaninteger
for artificial primary key columns.