From abca9e98d1ddf86e892bd23bd24878516225a2d1 Mon Sep 17 00:00:00 2001 From: Alvaro Herrera Date: Wed, 3 Jan 2018 12:36:47 -0300 Subject: [PATCH] Make XactLockTableWait work for transactions that are not yet self-locked MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit XactLockTableWait assumed that its xid argument has already added itself to the lock table. That assumption led to another assumption that if locking the xid has succeeded but the xid is reported as still in progress, then the input xid must have been a subtransaction. These assumptions hold true for the original uses of this code in locking related to on-disk tuples, but they break down in logical replication slot snapshot building -- in particular, when a standby snapshot logged contains an xid that's already in ProcArray but not yet in the lock table. This leads to assertion failures that can be reproduced all the way back to 9.4, when logical decoding was introduced. The new coding does not assume that the xid is a subtransaction anymore, and will retry the lock with same toplevel xid it was given before (courtesy of SubTransGetTopmostTransaction()). For consistency, change ConditionalXactLockTableWait the same way. Author: Petr Jelínek Discussion: https://postgr.es/m/1B3E32D8-FCF4-40B4-AEF9-5C0E3AC57969@postgrespro.ru Reported-by: Konstantin Knizhnik Diagnosed-by: Stas Kelvich, Petr Jelínek Reviewed-by: Andres Freund, Robert Haas --- src/backend/storage/lmgr/lmgr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 3754283d2b..c184f1f956 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -590,7 +590,7 @@ XactLockTableWait(TransactionId xid, Relation rel, ItemPointer ctid, if (!TransactionIdIsInProgress(xid)) break; - xid = SubTransGetParent(xid); + xid = SubTransGetTopmostTransaction(xid); } if (oper != XLTW_None) @@ -622,7 +622,7 @@ ConditionalXactLockTableWait(TransactionId xid) if (!TransactionIdIsInProgress(xid)) break; - xid = SubTransGetParent(xid); + xid = SubTransGetTopmostTransaction(xid); } return true; -- 2.11.0