diff --git a/lib/repack.c b/lib/repack.c index 3224544..ede7ebc 100644 --- a/lib/repack.c +++ b/lib/repack.c @@ -949,6 +949,28 @@ repack_drop(PG_FUNCTION_ARGS) /* connect to SPI manager */ repack_init(); + /* + * To prevent concurrent lockers of the repack target table from causing + * deadlocks, take an exclusive lock on it. Consider that the following + * commands take exclusive lock on tables log_xxx and the target table + * itself when deleting the z_repack_trigger on it, while concurrent + * updaters require row exclusive lock on the target table and in + * addition, on the log_xxx table, because of the trigger. + * + * Consider how a deadlock could occur - if the DROP TABLE repack.log_%u + * gets a lock on log_%u table before a concurrent updater could get it + * but after the updater has obtained a lock on the target table, the + * subsequent DROP TRIGGER ... ON target-table would report a deadlock as + * it finds itself waiting for a lock on target-table held by the updater, + * which in turn, is waiting for lock on log_%u table. + * + * Fixes deadlock mentioned in the Github issue #55. + */ + execute_with_format( + SPI_OK_UTILITY, + "LOCK TABLE %s.%s IN ACCESS EXCLUSIVE MODE", + nspname, relname); + /* drop log table: must be done before dropping the pk type, * since the log table is dependent on the pk type. (That's * why we check numobj > 1 here.)