Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit9f1e051

Browse files
committed
Truncate pg_multixact/'s contents during crash recovery
Commit9dc842f of 8.2 era prevented MultiXact truncation during crashrecovery, because there was no guarantee that enough state had beensetup, and because it wasn't deemed to be a good idea to remove dataduring crash recovery anyway. Since then, due to Hot-Standby, streamingreplication and PITR, the amount of time a cluster can spend doing crashrecovery has increased significantly, to the point that a cluster mayeven never come out of it. This has made not truncating the content ofpg_multixact/ not defensible anymore.To fix, take care to setup enough state for multixact truncation beforecrash recovery starts (easy since checkpoints contain the requiredinformation), and move the current end-of-recovery actions to a newTrimMultiXact() function, analogous to TrimCLOG().At some later point, this should probably done similarly to the wayclog.c is doing it, which is to just WAL log truncations, but we can'tdo that for the back branches.Back-patch to 9.0. 8.4 also has the problem, but since there's no hotstandby there, it's much less pressing. In 9.2 and earlier, this patchis simpler than in newer branches, because multixact access duringrecovery isn't required. Add appropriate checks to make sure that's nothappening.Andres Freund
1 parent8c72b20 commit9f1e051

File tree

1 file changed

+40
-14
lines changed

1 file changed

+40
-14
lines changed

‎src/backend/access/transam/multixact.c

Lines changed: 40 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,10 @@ GetNewMultiXactId(int nxids, MultiXactOffset *offset)
827827
/* MultiXactIdSetOldestMember() must have been called already */
828828
Assert(MultiXactIdIsValid(OldestMemberMXactId[MyBackendId]));
829829

830+
/* safety check, we should never get this far in a HS slave */
831+
if (RecoveryInProgress())
832+
elog(ERROR,"cannot assign MultiXactIds during recovery");
833+
830834
LWLockAcquire(MultiXactGenLock,LW_EXCLUSIVE);
831835

832836
/* Handle wraparound of the nextMXact counter */
@@ -914,6 +918,10 @@ GetMultiXactIdMembers(MultiXactId multi, TransactionId **xids)
914918

915919
Assert(MultiXactIdIsValid(multi));
916920

921+
/* safety check, we should never get this far in a HS slave */
922+
if (RecoveryInProgress())
923+
elog(ERROR,"cannot GetMultiXactIdMembers() during recovery");
924+
917925
/* See if the MultiXactId is in the local cache */
918926
length=mXactCacheGetById(multi,xids);
919927
if (length >=0)
@@ -1513,14 +1521,37 @@ ZeroMultiXactMemberPage(int pageno, bool writeXlog)
15131521
* This must be called ONCE during postmaster or standalone-backend startup.
15141522
*
15151523
* StartupXLOG has already established nextMXact/nextOffset by calling
1516-
* MultiXactSetNextMXact and/or MultiXactAdvanceNextMXact.Note that we
1517-
* may already have replayed WAL data into the SLRU files.
1518-
*
1519-
* We don't need any locks here, really; the SLRU locks are taken
1520-
* only because slru.c expects to be called with locks held.
1524+
* MultiXactSetNextMXact and/or MultiXactAdvanceNextMXact, but we haven't yet
1525+
* replayed WAL.
15211526
*/
15221527
void
15231528
StartupMultiXact(void)
1529+
{
1530+
MultiXactIdmulti=MultiXactState->nextMXact;
1531+
MultiXactOffsetoffset=MultiXactState->nextOffset;
1532+
intpageno;
1533+
1534+
/*
1535+
* Initialize our idea of the latest page number.
1536+
*/
1537+
pageno=MultiXactIdToOffsetPage(multi);
1538+
MultiXactOffsetCtl->shared->latest_page_number=pageno;
1539+
1540+
/*
1541+
* Initialize our idea of the latest page number.
1542+
*/
1543+
pageno=MXOffsetToMemberPage(offset);
1544+
MultiXactMemberCtl->shared->latest_page_number=pageno;
1545+
}
1546+
1547+
/*
1548+
* This must be called ONCE at the end of startup/recovery.
1549+
*
1550+
* We don't need any locks here, really; the SLRU locks are taken only because
1551+
* slru.c expects to be called with locks held.
1552+
*/
1553+
void
1554+
TrimMultiXact(void)
15241555
{
15251556
MultiXactIdmulti=MultiXactState->nextMXact;
15261557
MultiXactOffsetoffset=MultiXactState->nextOffset;
@@ -1531,7 +1562,7 @@ StartupMultiXact(void)
15311562
LWLockAcquire(MultiXactOffsetControlLock,LW_EXCLUSIVE);
15321563

15331564
/*
1534-
* Initialize our idea of the latest page number.
1565+
*(Re-)Initialize our idea of the latest page number.
15351566
*/
15361567
pageno=MultiXactIdToOffsetPage(multi);
15371568
MultiXactOffsetCtl->shared->latest_page_number=pageno;
@@ -1561,7 +1592,7 @@ StartupMultiXact(void)
15611592
LWLockAcquire(MultiXactMemberControlLock,LW_EXCLUSIVE);
15621593

15631594
/*
1564-
* Initialize our idea of the latest page number.
1595+
*(Re-)Initialize our idea of the latest page number.
15651596
*/
15661597
pageno=MXOffsetToMemberPage(offset);
15671598
MultiXactMemberCtl->shared->latest_page_number=pageno;
@@ -1640,14 +1671,9 @@ CheckPointMultiXact(void)
16401671

16411672
/*
16421673
* Truncate the SLRU files. This could be done at any time, but
1643-
* checkpoint seems a reasonable place for it.There is one exception: if
1644-
* we are called during xlog recovery, then shared->latest_page_number
1645-
* isn't valid (because StartupMultiXact hasn't been called yet) and so
1646-
* SimpleLruTruncate would get confused. It seems best not to risk
1647-
* removing any data during recovery anyway, so don't truncate.
1674+
* checkpoint seems a reasonable place for it.
16481675
*/
1649-
if (!RecoveryInProgress())
1650-
TruncateMultiXact();
1676+
TruncateMultiXact();
16511677

16521678
TRACE_POSTGRESQL_MULTIXACT_CHECKPOINT_DONE(true);
16531679
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp