Thread
-
ERROR during COMMIT PREPARED can leave orphaned locks
Daniil Davydov <3danissimo@gmail.com> — 2026-05-23T13:29:09Z
Hi, When finishing the prepared transaction, we are marking it as "not valid" after the WAL record has been written. This allows us to be sure that even if we fail later, no one will be able to commit/rollback this transaction again. Here is the code that implements it : ``` /* * In case we fail while running the callbacks, mark the gxact invalid so * no one else will try to commit/rollback, and so it will be recycled if * we fail after this point. It is still locked by our backend so it * won't go away yet. * * (We assume it's safe to do this without taking TwoPhaseStateLock.) */ gxact->valid = false; ``` Comment says that we can fail while running the callbacks. But if this really happens, then we are in trouble : 1) Twophase transaction we are working on is invalid, so AtAbort_Twophase will simply delete it from shmem. 2) Not all on-commit/on-rollback callbacks are completed, so (for example) transaction locks may remain. Thus, if the COMMIT/ROLLBACK PREPARED command faces an ERROR, the user 1) will not see the transaction in pg_prepared_xacts, but 2) will see its locks in pg_locks. IIUC, the only way to release these locks is to restart the server. I don't see any discussion about it on hackers, and I also don't see any sane fix for this problem. So, I decided to share it with you. Looking forward to your comments. Please, see the attached test that demonstrates the problem. Actually, reproduction is difficult. The only way to get an ERROR during callbacks execution is to trigger OOM. Since it is hard to implement from perl tests, I have added an injection point. (The patch can be applied to the newest master). -- Best regards, Daniil Davydov