From 015ddb48571dae1ae2316bf33785685053b63b5c Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Mon, 10 Jul 2023 12:02:44 +0300 Subject: [PATCH v2 3/3] Set databaseid when recovering an prepared SSI transaction. --- src/backend/access/transam/multixact.c | 8 ++++---- src/backend/access/transam/twophase.c | 12 ++++++------ src/backend/storage/lmgr/lock.c | 10 +++++----- src/backend/storage/lmgr/predicate.c | 14 ++++++-------- src/backend/utils/activity/pgstat_relation.c | 4 ++-- src/include/access/multixact.h | 6 +++--- src/include/access/twophase_rmgr.h | 2 +- src/include/pgstat.h | 4 ++-- src/include/storage/lock.h | 8 ++++---- src/include/storage/predicate.h | 2 +- 10 files changed, 34 insertions(+), 36 deletions(-) diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c index abb022e067..ac81b74b1f 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -1776,7 +1776,7 @@ PostPrepare_MultiXact(TransactionId xid) * Recover the state of a prepared transaction at startup */ void -multixact_twophase_recover(TransactionId xid, uint16 info, +multixact_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid, false); @@ -1797,7 +1797,7 @@ multixact_twophase_recover(TransactionId xid, uint16 info, * Similar to AtEOXact_MultiXact but for COMMIT PREPARED */ void -multixact_twophase_postcommit(TransactionId xid, uint16 info, +multixact_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { BackendId dummyBackendId = TwoPhaseGetDummyBackendId(xid, true); @@ -1812,10 +1812,10 @@ multixact_twophase_postcommit(TransactionId xid, uint16 info, * This is actually just the same as the COMMIT case. */ void -multixact_twophase_postabort(TransactionId xid, uint16 info, +multixact_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { - multixact_twophase_postcommit(xid, info, recdata, len); + multixact_twophase_postcommit(databaseid, xid, info, recdata, len); } /* diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 068e59bec0..fb9e4d16fa 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -219,7 +219,7 @@ static void RecordTransactionAbortPrepared(TransactionId xid, int nstats, xl_xact_stats_item *stats, const char *gid); -static void ProcessRecords(char *bufptr, TransactionId xid, +static void ProcessRecords(char *bufptr, Oid databaseid, TransactionId xid, const TwoPhaseCallback callbacks[]); static void RemoveGXact(GlobalTransaction gxact); @@ -1628,9 +1628,9 @@ FinishPreparedTransaction(const char *gid, bool isCommit) /* And now do the callbacks */ if (isCommit) - ProcessRecords(bufptr, xid, twophase_postcommit_callbacks); + ProcessRecords(bufptr, hdr->database, xid, twophase_postcommit_callbacks); else - ProcessRecords(bufptr, xid, twophase_postabort_callbacks); + ProcessRecords(bufptr, hdr->database, xid, twophase_postabort_callbacks); PredicateLockTwoPhaseFinish(xid, isCommit); @@ -1663,7 +1663,7 @@ FinishPreparedTransaction(const char *gid, bool isCommit) * Scan 2PC state data in memory and call the indicated callbacks for each 2PC record. */ static void -ProcessRecords(char *bufptr, TransactionId xid, +ProcessRecords(char *bufptr, Oid databaseid, TransactionId xid, const TwoPhaseCallback callbacks[]) { for (;;) @@ -1677,7 +1677,7 @@ ProcessRecords(char *bufptr, TransactionId xid, bufptr += MAXALIGN(sizeof(TwoPhaseRecordOnDisk)); if (callbacks[record->rmid] != NULL) - callbacks[record->rmid] (xid, record->info, + callbacks[record->rmid] (databaseid, xid, record->info, (void *) bufptr, record->len); bufptr += MAXALIGN(record->len); @@ -2123,7 +2123,7 @@ RecoverPreparedTransactions(void) /* * Recover other state (notably locks) using resource managers. */ - ProcessRecords(bufptr, xid, twophase_recover_callbacks); + ProcessRecords(bufptr, hdr->database, xid, twophase_recover_callbacks); /* * Release locks held by the standby process after we process each diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index f595bce31b..89f74ebee1 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -4122,7 +4122,7 @@ DumpAllLocks(void) * and PANIC anyway. */ void -lock_twophase_recover(TransactionId xid, uint16 info, +lock_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata; @@ -4303,7 +4303,7 @@ lock_twophase_recover(TransactionId xid, uint16 info, * starting up into hot standby mode. */ void -lock_twophase_standby_recover(TransactionId xid, uint16 info, +lock_twophase_standby_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata; @@ -4335,7 +4335,7 @@ lock_twophase_standby_recover(TransactionId xid, uint16 info, * Find and release the lock indicated by the 2PC record. */ void -lock_twophase_postcommit(TransactionId xid, uint16 info, +lock_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhaseLockRecord *rec = (TwoPhaseLockRecord *) recdata; @@ -4361,10 +4361,10 @@ lock_twophase_postcommit(TransactionId xid, uint16 info, * This is actually just the same as the COMMIT case. */ void -lock_twophase_postabort(TransactionId xid, uint16 info, +lock_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { - lock_twophase_postcommit(xid, info, recdata, len); + lock_twophase_postcommit(databaseid, xid, info, recdata, len); } /* diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c index fa05c801b4..edfa0e05fa 100644 --- a/src/backend/storage/lmgr/predicate.c +++ b/src/backend/storage/lmgr/predicate.c @@ -1826,13 +1826,11 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot, /* * We can't possibly have an unsafe conflict with a transaction in * another database. The only possible overlap is on shared - * catalogs, but we don't support SSI for shared catalogs. The - * invalid database case covers 2PC, because we don't yet record - * database OIDs in the 2PC information. We also filter out doomed - * transactions as they can't possibly commit. + * catalogs, but we don't support SSI for shared catalogs. We + * also filter out doomed transactions as they can't possibly + * commit. */ - if ((othersxact->database == InvalidOid || - othersxact->database == MyDatabaseId) + if (othersxact->database == MyDatabaseId && !SxactIsCommitted(othersxact) && !SxactIsDoomed(othersxact) && !SxactIsReadOnly(othersxact)) @@ -4859,7 +4857,7 @@ PredicateLockTwoPhaseFinish(TransactionId xid, bool isCommit) * Re-acquire a predicate lock belonging to a transaction that was prepared. */ void -predicatelock_twophase_recover(TransactionId xid, uint16 info, +predicatelock_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhasePredicateRecord *record; @@ -4894,7 +4892,7 @@ predicatelock_twophase_recover(TransactionId xid, uint16 info, sxact->vxid.localTransactionId = (LocalTransactionId) xid; sxact->pid = 0; sxact->pgprocno = INVALID_PGPROCNO; - sxact->database = InvalidOid; + sxact->database = databaseid; /* a prepared xact hasn't committed yet */ sxact->prepareSeqNo = RecoverySerCommitSeqNo; diff --git a/src/backend/utils/activity/pgstat_relation.c b/src/backend/utils/activity/pgstat_relation.c index 9876e0c1e8..87670318ed 100644 --- a/src/backend/utils/activity/pgstat_relation.c +++ b/src/backend/utils/activity/pgstat_relation.c @@ -699,7 +699,7 @@ PostPrepare_PgStat_Relations(PgStat_SubXactStatus *xact_state) * Load the saved counts into our local pgstats state. */ void -pgstat_twophase_postcommit(TransactionId xid, uint16 info, +pgstat_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata; @@ -735,7 +735,7 @@ pgstat_twophase_postcommit(TransactionId xid, uint16 info, * as aborted. */ void -pgstat_twophase_postabort(TransactionId xid, uint16 info, +pgstat_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len) { TwoPhasePgStatRecord *rec = (TwoPhasePgStatRecord *) recdata; diff --git a/src/include/access/multixact.h b/src/include/access/multixact.h index 246f757f6a..34646d15b5 100644 --- a/src/include/access/multixact.h +++ b/src/include/access/multixact.h @@ -149,11 +149,11 @@ extern void MultiXactAdvanceNextMXact(MultiXactId minMulti, extern void MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB); extern int MultiXactMemberFreezeThreshold(void); -extern void multixact_twophase_recover(TransactionId xid, uint16 info, +extern void multixact_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void multixact_twophase_postcommit(TransactionId xid, uint16 info, +extern void multixact_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void multixact_twophase_postabort(TransactionId xid, uint16 info, +extern void multixact_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); extern void multixact_redo(XLogReaderState *record); diff --git a/src/include/access/twophase_rmgr.h b/src/include/access/twophase_rmgr.h index 02f7ba2872..751284b617 100644 --- a/src/include/access/twophase_rmgr.h +++ b/src/include/access/twophase_rmgr.h @@ -14,7 +14,7 @@ #ifndef TWOPHASE_RMGR_H #define TWOPHASE_RMGR_H -typedef void (*TwoPhaseCallback) (TransactionId xid, uint16 info, +typedef void (*TwoPhaseCallback) (Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); typedef uint8 TwoPhaseRmgrId; diff --git a/src/include/pgstat.h b/src/include/pgstat.h index 57a2c0866a..f1a9fc8dcc 100644 --- a/src/include/pgstat.h +++ b/src/include/pgstat.h @@ -647,9 +647,9 @@ extern void pgstat_count_heap_delete(Relation rel); extern void pgstat_count_truncate(Relation rel); extern void pgstat_update_heap_dead_tuples(Relation rel, int delta); -extern void pgstat_twophase_postcommit(TransactionId xid, uint16 info, +extern void pgstat_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void pgstat_twophase_postabort(TransactionId xid, uint16 info, +extern void pgstat_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); extern PgStat_StatTabEntry *pgstat_fetch_stat_tabentry(Oid relid); diff --git a/src/include/storage/lock.h b/src/include/storage/lock.h index 8575bea25c..953609b37e 100644 --- a/src/include/storage/lock.h +++ b/src/include/storage/lock.h @@ -591,13 +591,13 @@ extern BlockedProcsData *GetBlockerStatusData(int blocked_pid); extern xl_standby_lock *GetRunningTransactionLocks(int *nlocks); extern const char *GetLockmodeName(LOCKMETHODID lockmethodid, LOCKMODE mode); -extern void lock_twophase_recover(TransactionId xid, uint16 info, +extern void lock_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void lock_twophase_postcommit(TransactionId xid, uint16 info, +extern void lock_twophase_postcommit(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void lock_twophase_postabort(TransactionId xid, uint16 info, +extern void lock_twophase_postabort(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); -extern void lock_twophase_standby_recover(TransactionId xid, uint16 info, +extern void lock_twophase_standby_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); extern DeadLockState DeadLockCheck(PGPROC *proc); diff --git a/src/include/storage/predicate.h b/src/include/storage/predicate.h index cd48afa17b..6a420a035c 100644 --- a/src/include/storage/predicate.h +++ b/src/include/storage/predicate.h @@ -77,7 +77,7 @@ extern void PreCommit_CheckForSerializationFailure(void); extern void AtPrepare_PredicateLocks(void); extern void PostPrepare_PredicateLocks(TransactionId xid); extern void PredicateLockTwoPhaseFinish(TransactionId xid, bool isCommit); -extern void predicatelock_twophase_recover(TransactionId xid, uint16 info, +extern void predicatelock_twophase_recover(Oid databaseid, TransactionId xid, uint16 info, void *recdata, uint32 len); /* parallel query support */ -- 2.30.2