1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-27 23:21:58 +03:00

Fix MVCC bug with prepared xact with subxacts on standby

We did not recover the subtransaction IDs of prepared transactions
when starting a hot standby from a shutdown checkpoint. As a result,
such subtransactions were considered as aborted, rather than
in-progress. That would lead to hint bits being set incorrectly, and
the subtransactions suddenly becoming visible to old snapshots when
the prepared transaction was committed.

To fix, update pg_subtrans with prepared transactions's subxids when
starting hot standby from a shutdown checkpoint. The snapshots taken
from that state need to be marked as "suboverflowed", so that we also
check the pg_subtrans.

Backport to all supported versions.

Discussion: https://www.postgresql.org/message-id/6b852e98-2d49-4ca1-9e95-db419a2696e0@iki.fi
This commit is contained in:
Heikki Linnakangas
2024-06-27 21:06:32 +03:00
parent 071e19a36c
commit e9c8747ee9
7 changed files with 85 additions and 18 deletions

View File

@ -7134,6 +7134,9 @@ StartupXLOG(void)
RunningTransactionsData running;
TransactionId latestCompletedXid;
/* Update pg_subtrans entries for any prepared transactions */
StandbyRecoverPreparedTransactions();
/*
* Construct a RunningTransactions snapshot representing a
* shut down server, with only prepared transactions still
@ -7142,7 +7145,7 @@ StartupXLOG(void)
*/
running.xcnt = nxids;
running.subxcnt = 0;
running.subxid_overflow = false;
running.subxid_status = SUBXIDS_IN_SUBTRANS;
running.nextXid = XidFromFullTransactionId(checkPoint.nextFullXid);
running.oldestRunningXid = oldestActiveXID;
latestCompletedXid = XidFromFullTransactionId(checkPoint.nextFullXid);
@ -7152,8 +7155,6 @@ StartupXLOG(void)
running.xids = xids;
ProcArrayApplyRecoveryInfo(&running);
StandbyRecoverPreparedTransactions();
}
}
@ -10217,6 +10218,9 @@ xlog_redo(XLogReaderState *record)
oldestActiveXID = PrescanPreparedTransactions(&xids, &nxids);
/* Update pg_subtrans entries for any prepared transactions */
StandbyRecoverPreparedTransactions();
/*
* Construct a RunningTransactions snapshot representing a shut
* down server, with only prepared transactions still alive. We're
@ -10225,7 +10229,7 @@ xlog_redo(XLogReaderState *record)
*/
running.xcnt = nxids;
running.subxcnt = 0;
running.subxid_overflow = false;
running.subxid_status = SUBXIDS_IN_SUBTRANS;
running.nextXid = XidFromFullTransactionId(checkPoint.nextFullXid);
running.oldestRunningXid = oldestActiveXID;
latestCompletedXid = XidFromFullTransactionId(checkPoint.nextFullXid);
@ -10235,8 +10239,6 @@ xlog_redo(XLogReaderState *record)
running.xids = xids;
ProcArrayApplyRecoveryInfo(&running);
StandbyRecoverPreparedTransactions();
}
/* ControlFile->checkPointCopy always tracks the latest ckpt XID */