standby_online_backup_09base_01fpw.patch
application/octet-stream
Filename: standby_online_backup_09base_01fpw.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/access/transam/xlog.c | 115 | 4 |
| src/backend/postmaster/walwriter.c | 11 | 0 |
| src/bin/pg_controldata/pg_controldata.c | 2 | 0 |
| src/bin/pg_resetxlog/pg_resetxlog.c | 3 | 0 |
| src/include/access/xlog.h | 1 | 0 |
| src/include/catalog/pg_control.h | 6 | 0 |
diff -rcN postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c postgresql_with_patch/src/backend/access/transam/xlog.c
*** postgresql_with_9fujii_patch/src/backend/access/transam/xlog.c 2011-10-06 06:06:19.000000000 +0900
--- postgresql_with_patch/src/backend/access/transam/xlog.c 2011-10-09 02:11:12.000000000 +0900
***************
*** 364,369 ****
--- 364,372 ----
bool exclusiveBackup;
int nonExclusiveBackups;
XLogRecPtr lastBackupStart;
+
+ /* the startup or the walwriter is logged to its own FPW */
+ bool fullPageWrites;
} XLogCtlInsert;
/*
***************
*** 453,458 ****
--- 456,464 ----
bool recoveryPause;
slock_t info_lck; /* locks shared variables shown above */
+
+ /* latest LSN that has recovered a WAL which fpw is changed 'off' */
+ XLogRecPtr lastFpwDisabledLSN;
} XLogCtlData;
static XLogCtlData *XLogCtl = NULL;
***************
*** 564,569 ****
--- 570,578 ----
/* Have we launched bgwriter during recovery? */
static bool bgwriterLaunched = false;
+ /* */
+ static bool master_fpw;
+
/*
* Information logged when we detect a change in one of the parameters
* important for Hot Standby.
***************
*** 763,769 ****
* don't yet have the insert lock, forcePageWrites could change under us,
* but we'll recheck it once we have the lock.
*/
! doPageWrites = fullPageWrites || Insert->forcePageWrites;
INIT_CRC32(rdata_crc);
len = 0;
--- 772,778 ----
* don't yet have the insert lock, forcePageWrites could change under us,
* but we'll recheck it once we have the lock.
*/
! doPageWrites = Insert->fullPageWrites || Insert->forcePageWrites;
INIT_CRC32(rdata_crc);
len = 0;
***************
*** 909,915 ****
* just turned off, we could recompute the record without full pages, but
* we choose not to bother.)
*/
! if (Insert->forcePageWrites && !doPageWrites)
{
/* Oops, must redo it with full-page data */
LWLockRelease(WALInsertLock);
--- 918,924 ----
* just turned off, we could recompute the record without full pages, but
* we choose not to bother.)
*/
! if ((Insert->fullPageWrites || Insert->forcePageWrites) && !doPageWrites)
{
/* Oops, must redo it with full-page data */
LWLockRelease(WALInsertLock);
***************
*** 6370,6377 ****
/* No need to hold ControlFileLock yet, we aren't up far enough */
UpdateControlFile();
! /* initialize our local copy of minRecoveryPoint */
minRecoveryPoint = ControlFile->minRecoveryPoint;
/*
* Reset pgstat data, because it may be invalid after recovery.
--- 6379,6387 ----
/* No need to hold ControlFileLock yet, we aren't up far enough */
UpdateControlFile();
! /* initialize our local copy of minRecoveryPoint and fullPageWrites */
minRecoveryPoint = ControlFile->minRecoveryPoint;
+ master_fpw = ControlFile->checkPointCopy.fullPageWrites;
/*
* Reset pgstat data, because it may be invalid after recovery.
***************
*** 6865,6870 ****
--- 6875,6889 ----
/* Pre-scan prepared transactions to find out the range of XIDs present */
oldestActiveXID = PrescanPreparedTransactions(NULL, NULL);
+ /*
+ * the startup updates FPW after REDO. However, it must perform before writing
+ * the WAL of the CHECKPOINT. This is because of the need to update own fpw to
+ * shared memory before writing the WAL of its CHECKPOTNT.
+ */
+ LocalSetXLogInsertAllowed();
+ ReportFpwParameters(true);
+ LocalXLogInsertAllowed = -1;
+
if (InRecovery)
{
int rmid;
***************
*** 7723,7728 ****
--- 7742,7750 ----
checkPoint.ThisTimeLineID = ThisTimeLineID;
+ /* record current FPW to the WAL of the CHECKPOINT. */
+ checkPoint.fullPageWrites = Insert->fullPageWrites;
+
/*
* Compute new REDO record ptr = location of next XLOG record.
*
***************
*** 8636,8641 ****
--- 8658,8676 ----
/* Check to see if any changes to max_connections give problems */
CheckRequiredParameterValues();
}
+ else if (info == XLOG_FPW_CHANGE)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ memcpy(&master_fpw, XLogRecGetData(record), sizeof(master_fpw));
+
+ /* record the LSN when FPW is changed false on master */
+ SpinLockAcquire(&xlogctl->info_lck);
+ if (!master_fpw)
+ xlogctl->lastFpwDisabledLSN = lsn;
+ SpinLockRelease(&xlogctl->info_lck);
+ }
}
void
***************
*** 8650,8656 ****
appendStringInfo(buf, "checkpoint: redo %X/%X; "
"tli %u; xid %u/%u; oid %u; multi %u; offset %u; "
! "oldest xid %u in DB %u; oldest running xid %u; %s",
checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
checkpoint->ThisTimeLineID,
checkpoint->nextXidEpoch, checkpoint->nextXid,
--- 8685,8691 ----
appendStringInfo(buf, "checkpoint: redo %X/%X; "
"tli %u; xid %u/%u; oid %u; multi %u; offset %u; "
! "oldest xid %u in DB %u; oldest running xid %u; full_page_writes %s; %s",
checkpoint->redo.xlogid, checkpoint->redo.xrecoff,
checkpoint->ThisTimeLineID,
checkpoint->nextXidEpoch, checkpoint->nextXid,
***************
*** 8660,8665 ****
--- 8695,8701 ----
checkpoint->oldestXid,
checkpoint->oldestXidDB,
checkpoint->oldestActiveXid,
+ checkpoint->fullPageWrites ? "true" : "false",
(info == XLOG_CHECKPOINT_SHUTDOWN) ? "shutdown" : "online");
}
else if (info == XLOG_NOOP)
***************
*** 8717,8722 ****
--- 8753,8766 ----
xlrec.max_locks_per_xact,
wal_level_str);
}
+ else if (info == XLOG_FPW_CHANGE)
+ {
+ bool fpw;
+
+ memcpy(&fpw, rec, sizeof(fpw));
+ appendStringInfo(buf, "fpw change: %s",
+ fpw ? "true" : "false");
+ }
else
appendStringInfo(buf, "UNKNOWN");
}
***************
*** 9089,9094 ****
--- 9133,9149 ----
gotUniqueStartpoint = true;
} while (!gotUniqueStartpoint);
+ /*
+ * check whether the master's FPW is 'off' when latest CHECKPOINT or
+ * since then.
+ */
+ if (recovery_in_progress &&
+ (!ControlFile->checkPointCopy.fullPageWrites ||
+ XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN)))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("full_page_writes on master is set invalid more than once since latest checkpoint")));
+
XLByteToSeg(startpoint, _logId, _logSeg);
XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
***************
*** 9372,9377 ****
--- 9427,9438 ----
"though pg_start_backup() was executed during recovery"),
errhint("The database backup will not be usable.")));
+ /* check whether the master's FPW is 'off' since pg_start_backup. */
+ if (recovery_in_progress && XLByteLE(startpoint, XLogCtl->lastFpwDisabledLSN))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("full_page_writes on master is set invalid more than once during online backup")));
+
/*
* During recovery, we don't write an end-of-backup record. We can
* assume that pg_control was backed up just before pg_stop_backup()
***************
*** 10743,10745 ****
--- 10804,10856 ----
{
SetLatch(&XLogCtl->recoveryWakeupLatch);
}
+
+ /*
+ * insert a WAL of XLOG_FPW_CHANGE or update to the shared memory if there
+ * is a change of FPW. However, always update when the startup have finished.
+ */
+ void
+ ReportFpwParameters(bool startup_finish)
+ {
+ bool fpwReport = false;
+ bool fpwXLogInsert = true;
+
+ if (startup_finish)
+ {
+ fpwReport = true;
+ if (master_fpw != fullPageWrites)
+ fpwXLogInsert = false;
+ }
+ else
+ {
+ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ if (XLogCtl->Insert.fullPageWrites != fullPageWrites)
+ fpwReport = true;
+ LWLockRelease(WALInsertLock);
+ }
+
+ if (fpwReport)
+ {
+ /*
+ * insert own fpw to a WAL. However, it does not perform
+ * when wal_level is not 'hotstandby' or fpw is same as shared-memory.
+ */
+ if (XLogStandbyInfoActive() && fpwXLogInsert)
+ {
+ XLogRecData rdata;
+ bool record = fullPageWrites;
+
+ rdata.buffer = InvalidBuffer;
+ rdata.data = (char *) &record;
+ rdata.len = sizeof(record);
+ rdata.next = NULL;
+
+ XLogInsert(RM_XLOG_ID, XLOG_FPW_CHANGE, &rdata);
+ }
+
+ /* update own fpw in shared-memory */
+ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ XLogCtl->Insert.fullPageWrites = fullPageWrites;
+ LWLockRelease(WALInsertLock);
+ }
+ }
diff -rcN postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c postgresql_with_patch/src/backend/postmaster/walwriter.c
*** postgresql_with_9fujii_patch/src/backend/postmaster/walwriter.c 2011-10-06 06:05:45.000000000 +0900
--- postgresql_with_patch/src/backend/postmaster/walwriter.c 2011-10-09 01:40:52.000000000 +0900
***************
*** 216,221 ****
--- 216,227 ----
PG_SETMASK(&UnBlockSig);
/*
+ * After the startup process, the walwriter manages the FPW. Because
+ * the walwriter may have not received a SIGHUP then, it updates the FPW.
+ */
+ ReportFpwParameters(false);
+
+ /*
* Loop forever
*/
for (;;)
***************
*** 236,241 ****
--- 242,252 ----
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
+ /*
+ * the walwriter manages the FPW. When the walwriter has received
+ * a SIGHUP, it updates the FPW.
+ */
+ ReportFpwParameters(false);
}
if (shutdown_requested)
{
diff -rcN postgresql_with_9fujii_patch/src/bin/pg_controldata/pg_controldata.c postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c
*** postgresql_with_9fujii_patch/src/bin/pg_controldata/pg_controldata.c 2011-10-06 06:06:19.000000000 +0900
--- postgresql_with_patch/src/bin/pg_controldata/pg_controldata.c 2011-10-09 01:40:52.000000000 +0900
***************
*** 224,229 ****
--- 224,231 ----
ControlFile.checkPointCopy.oldestXidDB);
printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
ControlFile.checkPointCopy.oldestActiveXid);
+ printf(_("Latest checkpoint's full_page_writes: %s\n"),
+ ControlFile.checkPointCopy.fullPageWrites ? "true" : "false");
printf(_("Time of latest checkpoint: %s\n"),
ckpttime_str);
printf(_("Minimum recovery ending location: %X/%X\n"),
diff -rcN postgresql_with_9fujii_patch/src/bin/pg_resetxlog/pg_resetxlog.c postgresql_with_patch/src/bin/pg_resetxlog/pg_resetxlog.c
*** postgresql_with_9fujii_patch/src/bin/pg_resetxlog/pg_resetxlog.c 2011-10-06 06:06:19.000000000 +0900
--- postgresql_with_patch/src/bin/pg_resetxlog/pg_resetxlog.c 2011-10-09 01:40:52.000000000 +0900
***************
*** 498,503 ****
--- 498,504 ----
ControlFile.checkPointCopy.oldestXidDB = InvalidOid;
ControlFile.checkPointCopy.time = (pg_time_t) time(NULL);
ControlFile.checkPointCopy.oldestActiveXid = InvalidTransactionId;
+ ControlFile.checkPointCopy.fullPageWrites = true;
ControlFile.state = DB_SHUTDOWNED;
ControlFile.time = (pg_time_t) time(NULL);
***************
*** 584,589 ****
--- 585,592 ----
ControlFile.checkPointCopy.oldestXidDB);
printf(_("Latest checkpoint's oldestActiveXID: %u\n"),
ControlFile.checkPointCopy.oldestActiveXid);
+ printf(_("Latest checkpoint's full_page_writes: %s\n"),
+ ControlFile.checkPointCopy.fullPageWrites ? "true" : "false");
printf(_("Maximum data alignment: %u\n"),
ControlFile.maxAlign);
/* we don't print floatFormat since can't say much useful about it */
diff -rcN postgresql_with_9fujii_patch/src/include/access/xlog.h postgresql_with_patch/src/include/access/xlog.h
*** postgresql_with_9fujii_patch/src/include/access/xlog.h 2011-10-06 06:05:45.000000000 +0900
--- postgresql_with_patch/src/include/access/xlog.h 2011-10-09 01:40:52.000000000 +0900
***************
*** 316,321 ****
--- 316,322 ----
extern void StartupProcessMain(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
+ extern void ReportFpwParameters(bool startup_finish);
/*
* Starting/stopping a base backup
diff -rcN postgresql_with_9fujii_patch/src/include/catalog/pg_control.h postgresql_with_patch/src/include/catalog/pg_control.h
*** postgresql_with_9fujii_patch/src/include/catalog/pg_control.h 2011-10-06 06:06:19.000000000 +0900
--- postgresql_with_patch/src/include/catalog/pg_control.h 2011-10-09 01:40:51.000000000 +0900
***************
*** 49,54 ****
--- 49,59 ----
* it's set to InvalidTransactionId.
*/
TransactionId oldestActiveXid;
+
+ /*
+ * current FPW. It is used when executing pg_start_backup on hot standby.
+ */
+ bool fullPageWrites;
} CheckPoint;
/* XLOG info values for XLOG rmgr */
***************
*** 60,65 ****
--- 65,71 ----
#define XLOG_BACKUP_END 0x50
#define XLOG_PARAMETER_CHANGE 0x60
#define XLOG_RESTORE_POINT 0x70
+ #define XLOG_FPW_CHANGE 0x80
/*