standby_online_backup_09base-07fpw.patch
application/octet-stream
Filename: standby_online_backup_09base-07fpw.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 | 143 | 9 |
| src/backend/postmaster/walwriter.c | 13 | 0 |
| src/include/access/xlog.h | 12 | 0 |
| src/include/catalog/pg_control.h | 1 | 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-19 07:02:07.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 'off' */
+ XLogRecPtr lastFpwDisabledLSN;
} XLogCtlData;
static XLogCtlData *XLogCtl = NULL;
***************
*** 759,769 ****
/*
* Decide if we need to do full-page writes in this XLOG record: true if
! * full_page_writes is on or we have a PITR request for it. Since we
! * 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;
--- 765,776 ----
/*
* Decide if we need to do full-page writes in this XLOG record: true if
! * full_page_writes in shared-memory is on or we have a PITR request for
! * it. Since we don't yet have the insert lock, fullPageWrites or
! * 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;
***************
*** 904,915 ****
}
/*
! * Also check to see if forcePageWrites was just turned on; if we weren't
! * already doing full-page writes then go back and recompute. (If it was
! * 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);
--- 911,922 ----
}
/*
! * Also check to see if fullPageWrites or forcePageWrites was just
! * turned on; if we weren't already doing full-page writes then go back
! * and recompute. (If it was 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);
***************
*** 7001,7006 ****
--- 7008,7020 ----
XLogReportParameters();
/*
+ * The startup updates FPW after REDO. ReportFpwParameters() is called
+ * here because it is not called on checkpoint after REDO.
+ * It is safe because we cannot update data during the startup running.
+ */
+ ReportFpwParameters(REPORT_ON_STARTUP);
+
+ /*
* All done. Allow backends to write WAL. (Although the bool flag is
* probably atomic in itself, we use the info_lck here to ensure that
* there are no race conditions concerning visibility of other recent
***************
*** 7856,7862 ****
--- 7870,7885 ----
* Update checkPoint.nextXid since we have a later value
*/
if (!shutdown && XLogStandbyInfoActive())
+ {
LogStandbySnapshot(&checkPoint.oldestActiveXid, &checkPoint.nextXid);
+
+ /*
+ * The bgwriter writes WAL of FPW at checkpoint. But does not at shutdown.
+ * Because ReportFpwParameters() is always called at the end of startup
+ * process, it does not need to be called at shutdown.
+ */
+ ReportFpwParameters(REPORT_ON_BGWRITER);
+ }
else
checkPoint.oldestActiveXid = InvalidTransactionId;
***************
*** 8636,8641 ****
--- 8659,8681 ----
/* 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;
+
+ bool fpw;
+
+ memcpy(&fpw, XLogRecGetData(record), sizeof(fpw));
+
+ /* record the LSN when FPW is false on master */
+ if (!fpw)
+ {
+ SpinLockAcquire(&xlogctl->info_lck);
+ xlogctl->lastFpwDisabledLSN = lsn;
+ SpinLockRelease(&xlogctl->info_lck);
+ }
+ }
}
void
***************
*** 8717,8722 ****
--- 8757,8770 ----
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: full_page_writes=%s",
+ fpw ? "true" : "false");
+ }
else
appendStringInfo(buf, "UNKNOWN");
}
***************
*** 8933,8938 ****
--- 8981,8987 ----
bool recovery_in_progress = false;
XLogRecPtr checkpointloc;
XLogRecPtr startpoint;
+ XLogRecPtr lastFpwDisabledLSN;
pg_time_t stamp_time;
char strfbuf[128];
char xlogfilename[MAXFNAMELEN];
***************
*** 9089,9094 ****
--- 9138,9161 ----
gotUniqueStartpoint = true;
} while (!gotUniqueStartpoint);
+ /*
+ * check whether the master's FPW is 'off' since latest CHECKPOINT.
+ */
+ if (recovery_in_progress)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ SpinLockAcquire(&xlogctl->info_lck);
+ lastFpwDisabledLSN = xlogctl->lastFpwDisabledLSN;
+ SpinLockRelease(&xlogctl->info_lck);
+
+ if (XLByteLE(startpoint, lastFpwDisabledLSN))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("WAL generated with full_page_writes=off was replayed since latest checkpoint")));
+ }
+
XLByteToSeg(startpoint, _logId, _logSeg);
XLogFileName(xlogfilename, ThisTimeLineID, _logId, _logSeg);
***************
*** 9233,9238 ****
--- 9300,9306 ----
bool recovery_in_progress = false;
XLogRecPtr startpoint;
XLogRecPtr stoppoint;
+ XLogRecPtr lastFpwDisabledLSN;
XLogRecData rdata;
pg_time_t stamp_time;
char strfbuf[128];
***************
*** 9372,9377 ****
--- 9440,9461 ----
"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)
+ {
+ /* use volatile pointer to prevent code rearrangement */
+ volatile XLogCtlData *xlogctl = XLogCtl;
+
+ SpinLockAcquire(&xlogctl->info_lck);
+ lastFpwDisabledLSN = xlogctl->lastFpwDisabledLSN;
+ SpinLockRelease(&xlogctl->info_lck);
+
+ if (XLByteLE(startpoint, lastFpwDisabledLSN))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("WAL generated with full_page_writes=off was replayed 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 ****
--- 10827,10879 ----
{
SetLatch(&XLogCtl->recoveryWakeupLatch);
}
+
+ /*
+ * Insert a WAL of XLOG_FPW_CHANGE or update to the shared memory.
+ * The called timing is at checkpoint, at the end of startup or at receiving
+ * SIGHUP on walwriter.
+ * checkpoint: insert, but not update.
+ * startup: insert and update.
+ * walwriter: insert and update if FPW was changed.
+ */
+ void
+ ReportFpwParameters(int updatetiming)
+ {
+ bool fpw = fullPageWrites;
+
+ if (updatetiming == REPORT_ON_BGWRITER)
+ {
+ LWLockAcquire(WALInsertLock, LW_EXCLUSIVE);
+ fpw = XLogCtl->Insert.fullPageWrites;
+ LWLockRelease(WALInsertLock);
+ }
+
+ if (updatetiming <= REPORT_ON_STARTUP ||
+ (updatetiming == REPORT_ON_WALWRITER && fpw != XLogCtl->Insert.fullPageWrites))
+ {
+ /*
+ * 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())
+ {
+ 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 when it has managed fpw */
+ if (updatetiming >= REPORT_ON_STARTUP)
+ {
+ 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-19 07:02:07.000000000 +0900
***************
*** 216,221 ****
--- 216,228 ----
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
+ * when wal_level is hotstandby.
+ */
+ ReportFpwParameters(REPORT_ON_WALWRITER);
+
+ /*
* Loop forever
*/
for (;;)
***************
*** 236,241 ****
--- 243,254 ----
{
got_SIGHUP = false;
ProcessConfigFile(PGC_SIGHUP);
+
+ /*
+ * The walwriter manages the FPW. When the walwriter has received
+ * a SIGHUP, when wal_level is hotstandby, it updates the FPW.
+ */
+ ReportFpwParameters(REPORT_ON_WALWRITER);
}
if (shutdown_requested)
{
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-19 07:02:07.000000000 +0900
***************
*** 208,213 ****
--- 208,224 ----
} WalLevel;
extern int wal_level;
+ /*
+ * The place of updating xlog parameter.
+ * If it is backend then this means a timing for CHECKPOINT.
+ */
+ typedef enum
+ {
+ REPORT_ON_BGWRITER = 0,
+ REPORT_ON_STARTUP,
+ REPORT_ON_WALWRITER
+ } XLogParemeterUpdate;
+
#define XLogArchivingActive() (XLogArchiveMode && wal_level >= WAL_LEVEL_ARCHIVE)
#define XLogArchiveCommandSet() (XLogArchiveCommand[0] != '\0')
***************
*** 316,321 ****
--- 327,333 ----
extern void StartupProcessMain(void);
extern bool CheckPromoteSignal(void);
extern void WakeupRecovery(void);
+ extern void ReportFpwParameters(int updatetiming);
/*
* 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-19 07:02:07.000000000 +0900
***************
*** 60,65 ****
--- 60,66 ----
#define XLOG_BACKUP_END 0x50
#define XLOG_PARAMETER_CHANGE 0x60
#define XLOG_RESTORE_POINT 0x70
+ #define XLOG_FPW_CHANGE 0x80
/*