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:
@ -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 */
|
||||
|
Reference in New Issue
Block a user