diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 0a8edb9..1727c56 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -2056,11 +2056,15 @@ RecordTransactionCommitPrepared(TransactionId xid, /* See notes in RecordTransactionCommit */ MyPgXact->delayChkpt = true; - /* Emit the XLOG commit record */ + /* + * Emit the XLOG commit record. Note that we mark 2PC commits as potentially + * having AccessExclusiveLocks since we don't know whether or not they do. + */ recptr = XactLogCommitRecord(committs, nchildren, children, nrels, rels, ninvalmsgs, invalmsgs, initfileinval, false, + true, xid); diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 82f9a3c..b45e919 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -115,6 +115,11 @@ TransactionId *ParallelCurrentXids; */ bool MyXactAccessedTempRel = false; +/* + * MyXactAcquiredAccessExclusiveLock is set when we log an + * AccessExclusiveLock. (Global so we can set from standby.c) + */ +bool MyXactAcquiredAccessExclusiveLock = false; /* * transaction states - transaction state from server perspective @@ -1231,6 +1236,7 @@ RecordTransactionCommit(void) nchildren, children, nrels, rels, nmsgs, invalMessages, RelcacheInitFileInval, forceSyncCommit, + MyXactAcquiredAccessExclusiveLock, InvalidTransactionId /* plain commit */ ); if (replorigin) @@ -1846,6 +1852,7 @@ StartTransaction(void) XactIsoLevel = DefaultXactIsoLevel; forceSyncCommit = false; MyXactAccessedTempRel = false; + MyXactAcquiredAccessExclusiveLock = false; /* * reinitialize within-transaction counters @@ -5100,7 +5107,8 @@ xactGetCommittedChildren(TransactionId **ptr) * Log the commit record for a plain or twophase transaction commit. * * A 2pc commit will be emitted when twophase_xid is valid, a plain one - * otherwise. + * otherwise. 2pc commits set acquiredAccessExclusiveLock, which is a + * false positive but that's OK since it was just for performance. */ XLogRecPtr XactLogCommitRecord(TimestampTz commit_time, @@ -5108,6 +5116,7 @@ XactLogCommitRecord(TimestampTz commit_time, int nrels, RelFileNode *rels, int nmsgs, SharedInvalidationMessage *msgs, bool relcacheInval, bool forceSync, + bool acquiredAccessExclusiveLock, TransactionId twophase_xid) { xl_xact_commit xlrec; @@ -5139,6 +5148,8 @@ XactLogCommitRecord(TimestampTz commit_time, xl_xinfo.xinfo |= XACT_COMPLETION_UPDATE_RELCACHE_FILE; if (forceSyncCommit) xl_xinfo.xinfo |= XACT_COMPLETION_FORCE_SYNC_COMMIT; + if (acquiredAccessExclusiveLock) + xl_xinfo.xinfo |= XACT_XINFO_HAS_AE_LOCKS; /* * Check if the caller would like to ask standbys for immediate feedback @@ -5427,7 +5438,8 @@ xact_redo_commit(xl_xact_parsed_commit *parsed, * via their top-level xid only, so no need to provide subxact list, * which will save time when replaying commits. */ - StandbyReleaseLockTree(xid, 0, NULL); + if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS) + StandbyReleaseLockTree(xid, 0, NULL); } if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN) @@ -5563,7 +5575,8 @@ xact_redo_abort(xl_xact_parsed_abort *parsed, TransactionId xid) /* * Release locks, if any. There are no invalidations to send. */ - StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts); + if (parsed->xinfo & XACT_XINFO_HAS_AE_LOCKS) + StandbyReleaseLockTree(xid, parsed->nsubxacts, parsed->subxacts); } /* Make sure files supposed to be dropped are dropped */ diff --git a/src/backend/storage/ipc/standby.c b/src/backend/storage/ipc/standby.c index 6259070..0ec81eb 100644 --- a/src/backend/storage/ipc/standby.c +++ b/src/backend/storage/ipc/standby.c @@ -1063,6 +1063,7 @@ LogAccessExclusiveLock(Oid dbOid, Oid relOid) xlrec.relOid = relOid; LogAccessExclusiveLocks(1, &xlrec); + MyXactAcquiredAccessExclusiveLock = true; } /* diff --git a/src/include/access/xact.h b/src/include/access/xact.h index e7d1191..3c9348c 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -73,6 +73,7 @@ extern int synchronous_commit; /* Kluge for 2PC support */ extern bool MyXactAccessedTempRel; +extern bool MyXactAcquiredAccessExclusiveLock; /* * start- and end-of-transaction callbacks for dynamically loaded modules @@ -137,6 +138,7 @@ typedef void (*SubXactCallback) (SubXactEvent event, SubTransactionId mySubid, #define XACT_XINFO_HAS_INVALS (1U << 3) #define XACT_XINFO_HAS_TWOPHASE (1U << 4) #define XACT_XINFO_HAS_ORIGIN (1U << 5) +#define XACT_XINFO_HAS_AE_LOCKS (1U << 6) /* * Also stored in xinfo, these indicating a variety of additional actions that @@ -364,6 +366,7 @@ extern XLogRecPtr XactLogCommitRecord(TimestampTz commit_time, int nrels, RelFileNode *rels, int nmsgs, SharedInvalidationMessage *msgs, bool relcacheInval, bool forceSync, + bool acquiredAccessExclusiveLock, TransactionId twophase_xid); extern XLogRecPtr XactLogAbortRecord(TimestampTz abort_time,