Commit aa29c1cc authored by Andres Freund's avatar Andres Freund

Remove legacy multixact truncation support.

In 9.5 and master there is no need to support legacy truncation. This is
just committed separately to make it easier to backpatch the WAL logged
multixact truncation to 9.3 and 9.4 if we later decide to do so.

I bumped master's magic from 0xD086 to 0xD088 and 9.5's from 0xD085 to
0xD087 to avoid 9.5 reusing a value that has been in use on master while
keeping the numbers increasing between major versions.

Discussion: 20150621192409.GA4797@alap3.anarazel.de
Backpatch: 9.5
parent 4f627f89
...@@ -220,14 +220,6 @@ typedef struct MultiXactStateData ...@@ -220,14 +220,6 @@ typedef struct MultiXactStateData
MultiXactOffset oldestOffset; MultiXactOffset oldestOffset;
bool oldestOffsetKnown; bool oldestOffsetKnown;
/*
* True if a multixact truncation WAL record was replayed since the last
* checkpoint. This is used to trigger 'legacy truncations', i.e. truncate
* by looking at the data directory during WAL replay, when the primary is
* too old to generate truncation records.
*/
bool sawTruncationInCkptCycle;
/* support for anti-wraparound measures */ /* support for anti-wraparound measures */
MultiXactId multiVacLimit; MultiXactId multiVacLimit;
MultiXactId multiWarnLimit; MultiXactId multiWarnLimit;
...@@ -2381,28 +2373,7 @@ MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB) ...@@ -2381,28 +2373,7 @@ MultiXactAdvanceOldest(MultiXactId oldestMulti, Oid oldestMultiDB)
Assert(InRecovery); Assert(InRecovery);
if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti)) if (MultiXactIdPrecedes(MultiXactState->oldestMultiXactId, oldestMulti))
{
/*
* If there has been a truncation on the master, detected by seeing a
* moving oldestMulti, without a corresponding truncation record, we
* know that the primary is still running an older version of postgres
* that doesn't yet log multixact truncations. So perform the
* truncation ourselves.
*/
if (!MultiXactState->sawTruncationInCkptCycle)
{
ereport(LOG,
(errmsg("performing legacy multixact truncation"),
errdetail("Legacy truncations are sometimes performed when replaying WAL from an older primary."),
errhint("Upgrade the primary, it is susceptible to data corruption.")));
TruncateMultiXact(oldestMulti, oldestMultiDB, true);
}
SetMultiXactIdLimit(oldestMulti, oldestMultiDB); SetMultiXactIdLimit(oldestMulti, oldestMultiDB);
}
/* only looked at in the startup process, no lock necessary */
MultiXactState->sawTruncationInCkptCycle = false;
} }
/* /*
...@@ -2747,8 +2718,7 @@ find_multixact_start(MultiXactId multi, MultiXactOffset *result) ...@@ -2747,8 +2718,7 @@ find_multixact_start(MultiXactId multi, MultiXactOffset *result)
int slotno; int slotno;
MultiXactOffset *offptr; MultiXactOffset *offptr;
/* XXX: Remove || AmStartupProcess() after WAL page magic bump */ Assert(MultiXactState->finishedStartup);
Assert(MultiXactState->finishedStartup || AmStartupProcess());
pageno = MultiXactIdToOffsetPage(multi); pageno = MultiXactIdToOffsetPage(multi);
entryno = MultiXactIdToOffsetEntry(multi); entryno = MultiXactIdToOffsetEntry(multi);
...@@ -2946,18 +2916,15 @@ PerformOffsetsTruncation(MultiXactId oldestMulti, MultiXactId newOldestMulti) ...@@ -2946,18 +2916,15 @@ PerformOffsetsTruncation(MultiXactId oldestMulti, MultiXactId newOldestMulti)
* Remove all MultiXactOffset and MultiXactMember segments before the oldest * Remove all MultiXactOffset and MultiXactMember segments before the oldest
* ones still of interest. * ones still of interest.
* *
* On a primary this is called as part of vacuum (via * This is only called on a primary as part of vacuum (via
* vac_truncate_clog()). During recovery truncation is normally done by * vac_truncate_clog()). During recovery truncation is done by replaying
* replaying truncation WAL records instead of this routine; the exception is * truncation WAL records logged here.
* when replaying records from an older primary that doesn't yet generate
* truncation WAL records. In that case truncation is triggered by
* MultiXactAdvanceOldest().
* *
* newOldestMulti is the oldest currently required multixact, newOldestMultiDB * newOldestMulti is the oldest currently required multixact, newOldestMultiDB
* is one of the databases preventing newOldestMulti from increasing. * is one of the databases preventing newOldestMulti from increasing.
*/ */
void void
TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_recovery) TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB)
{ {
MultiXactId oldestMulti; MultiXactId oldestMulti;
MultiXactId nextMulti; MultiXactId nextMulti;
...@@ -2967,13 +2934,8 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco ...@@ -2967,13 +2934,8 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco
mxtruncinfo trunc; mxtruncinfo trunc;
MultiXactId earliest; MultiXactId earliest;
/* Assert(!RecoveryInProgress());
* Need to allow being called in recovery for backwards compatibility, Assert(MultiXactState->finishedStartup);
* when an updated standby replays WAL generated by a non-updated primary.
*/
Assert(in_recovery || !RecoveryInProgress());
Assert(!in_recovery || AmStartupProcess());
Assert(in_recovery || MultiXactState->finishedStartup);
/* /*
* We can only allow one truncation to happen at once. Otherwise parts of * We can only allow one truncation to happen at once. Otherwise parts of
...@@ -3086,22 +3048,15 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco ...@@ -3086,22 +3048,15 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco
* Prevent checkpoints from being scheduled concurrently. This is critical * Prevent checkpoints from being scheduled concurrently. This is critical
* because otherwise a truncation record might not be replayed after a * because otherwise a truncation record might not be replayed after a
* crash/basebackup, even though the state of the data directory would * crash/basebackup, even though the state of the data directory would
* require it. It's not possible (startup process doesn't have a PGXACT * require it.
* entry), and not needed, to do this during recovery, when performing an
* old-style truncation, though. There the entire scheduling depends on
* the replayed WAL records which be the same after a possible crash.
*/ */
if (!in_recovery) Assert(!MyPgXact->delayChkpt);
{ MyPgXact->delayChkpt = true;
Assert(!MyPgXact->delayChkpt);
MyPgXact->delayChkpt = true;
}
/* WAL log truncation */ /* WAL log truncation */
if (!in_recovery) WriteMTruncateXlogRec(newOldestMultiDB,
WriteMTruncateXlogRec(newOldestMultiDB, oldestMulti, newOldestMulti,
oldestMulti, newOldestMulti, oldestOffset, newOldestOffset);
oldestOffset, newOldestOffset);
/* /*
* Update in-memory limits before performing the truncation, while inside * Update in-memory limits before performing the truncation, while inside
...@@ -3122,8 +3077,7 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco ...@@ -3122,8 +3077,7 @@ TruncateMultiXact(MultiXactId newOldestMulti, Oid newOldestMultiDB, bool in_reco
/* Then offsets */ /* Then offsets */
PerformOffsetsTruncation(oldestMulti, newOldestMulti); PerformOffsetsTruncation(oldestMulti, newOldestMulti);
if (!in_recovery) MyPgXact->delayChkpt = false;
MyPgXact->delayChkpt = false;
END_CRIT_SECTION(); END_CRIT_SECTION();
LWLockRelease(MultiXactTruncationLock); LWLockRelease(MultiXactTruncationLock);
...@@ -3371,9 +3325,6 @@ multixact_redo(XLogReaderState *record) ...@@ -3371,9 +3325,6 @@ multixact_redo(XLogReaderState *record)
PerformOffsetsTruncation(xlrec.startTruncOff, xlrec.endTruncOff); PerformOffsetsTruncation(xlrec.startTruncOff, xlrec.endTruncOff);
LWLockRelease(MultiXactTruncationLock); LWLockRelease(MultiXactTruncationLock);
/* only looked at in the startup process, no lock necessary */
MultiXactState->sawTruncationInCkptCycle = true;
} }
else else
elog(PANIC, "multixact_redo: unknown op code %u", info); elog(PANIC, "multixact_redo: unknown op code %u", info);
......
...@@ -9233,10 +9233,6 @@ xlog_redo(XLogReaderState *record) ...@@ -9233,10 +9233,6 @@ xlog_redo(XLogReaderState *record)
MultiXactSetNextMXact(checkPoint.nextMulti, MultiXactSetNextMXact(checkPoint.nextMulti,
checkPoint.nextMultiOffset); checkPoint.nextMultiOffset);
/*
* NB: This may perform multixact truncation when replaying WAL
* generated by an older primary.
*/
MultiXactAdvanceOldest(checkPoint.oldestMulti, MultiXactAdvanceOldest(checkPoint.oldestMulti,
checkPoint.oldestMultiDB); checkPoint.oldestMultiDB);
SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB); SetTransactionIdLimit(checkPoint.oldestXid, checkPoint.oldestXidDB);
......
...@@ -1141,7 +1141,7 @@ vac_truncate_clog(TransactionId frozenXID, ...@@ -1141,7 +1141,7 @@ vac_truncate_clog(TransactionId frozenXID,
*/ */
TruncateCLOG(frozenXID); TruncateCLOG(frozenXID);
TruncateCommitTs(frozenXID, true); TruncateCommitTs(frozenXID, true);
TruncateMultiXact(minMulti, minmulti_datoid, false); TruncateMultiXact(minMulti, minmulti_datoid);
/* /*
* Update the wrap limit for GetNewTransactionId and creation of new * Update the wrap limit for GetNewTransactionId and creation of new
......
...@@ -135,7 +135,7 @@ extern void MultiXactGetCheckptMulti(bool is_shutdown, ...@@ -135,7 +135,7 @@ extern void MultiXactGetCheckptMulti(bool is_shutdown,
Oid *oldestMultiDB); Oid *oldestMultiDB);
extern void CheckPointMultiXact(void); extern void CheckPointMultiXact(void);
extern MultiXactId GetOldestMultiXactId(void); extern MultiXactId GetOldestMultiXactId(void);
extern void TruncateMultiXact(MultiXactId oldestMulti, Oid oldestMultiDB, bool in_recovery); extern void TruncateMultiXact(MultiXactId oldestMulti, Oid oldestMultiDB);
extern void MultiXactSetNextMXact(MultiXactId nextMulti, extern void MultiXactSetNextMXact(MultiXactId nextMulti,
MultiXactOffset nextMultiOffset); MultiXactOffset nextMultiOffset);
extern void MultiXactAdvanceNextMXact(MultiXactId minMulti, extern void MultiXactAdvanceNextMXact(MultiXactId minMulti,
......
...@@ -31,7 +31,7 @@ ...@@ -31,7 +31,7 @@
/* /*
* Each page of XLOG file has a header like this: * Each page of XLOG file has a header like this:
*/ */
#define XLOG_PAGE_MAGIC 0xD086 /* can be used as WAL version indicator */ #define XLOG_PAGE_MAGIC 0xD088 /* can be used as WAL version indicator */
typedef struct XLogPageHeaderData typedef struct XLogPageHeaderData
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment