When using 2PC (two phase commit), you may end up in a situation where you kind of have something locked, but cannot find a backend that holds the locks.
db=# select t.schemaname || '.' || t.relname as tablename, db-# l.pid, l.granted db-# from pg_locks l join pg_stat_user_tables t db-# on l.relation = t.relid; tablename | pid | granted -----------+-------+--------- db.x | | t db.x | 27289 | f (2 rows)
has a lock on table
db.x, which has no process associated with it.
Look at the recipe on Removing old prepared transactions in Regular Maintenance