*** a/doc/src/sgml/config.sgml
--- b/doc/src/sgml/config.sgml
***************
*** 1876,1881 **** include 'filename'
--- 1876,1920 ----
+
+ wal_log_hintbits (boolean)
+
+ wal_log_hintbits> configuration parameter
+
+
+
+ When this parameter is on>, the PostgreSQL>
+ server writes the full page image of disk page to WAL during first time
+ updating the hint bits for that page after a checkpoint. This is needed
+ to maintain file system level consistency between master and standby
+ server in terms of hint bits.
+
+
+
+ This functionality is useful for differential backups as well as to speed
+ up failback operation by avoiding need of fresh backup in Streaming Replication.
+
+
+
+ Turning on this parameter generates more WAL than normal operation but it
+ has some performance improvement on standby side. Standby receives readymade
+ WAL records for each changed hint bit and those can get directly replayed
+ like other WAL.
+
+
+
+ The feature is little bit similar to checksum feature, the only difference
+ is that WAL gets generated only when hint bits get updated and checksum
+ calculation part gets skipped. PostgreSQL will skip this functionality
+ if you already have checksum feature enabled.
+
+
+
+ This parameter can only be set at server start. The default value is off>.
+
+
+
+
wal_buffers (integer)
*** a/src/backend/access/transam/xlog.c
--- b/src/backend/access/transam/xlog.c
***************
*** 79,84 **** bool XLogArchiveMode = false;
--- 79,85 ----
char *XLogArchiveCommand = NULL;
bool EnableHotStandby = false;
bool fullPageWrites = true;
+ bool walLogHintbits = false;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
***************
*** 5265,5270 **** BootStrapXLOG(void)
--- 5266,5272 ----
ControlFile->max_locks_per_xact = max_locks_per_xact;
ControlFile->wal_level = wal_level;
ControlFile->data_checksum_version = bootstrap_data_checksum_version;
+ ControlFile->wal_log_hintbits = walLogHintbits;
/* some additional ControlFile fields are set in WriteControlFile() */
***************
*** 8921,8926 **** static void
--- 8923,8929 ----
XLogReportParameters(void)
{
if (wal_level != ControlFile->wal_level ||
+ walLogHintbits != ControlFile->wal_log_hintbits ||
MaxConnections != ControlFile->MaxConnections ||
max_worker_processes != ControlFile->max_worker_processes ||
max_prepared_xacts != ControlFile->max_prepared_xacts ||
***************
*** 8943,8948 **** XLogReportParameters(void)
--- 8946,8952 ----
xlrec.max_prepared_xacts = max_prepared_xacts;
xlrec.max_locks_per_xact = max_locks_per_xact;
xlrec.wal_level = wal_level;
+ xlrec.wal_log_hintbits = walLogHintbits;
rdata.buffer = InvalidBuffer;
rdata.data = (char *) &xlrec;
***************
*** 8957,8962 **** XLogReportParameters(void)
--- 8961,8967 ----
ControlFile->max_prepared_xacts = max_prepared_xacts;
ControlFile->max_locks_per_xact = max_locks_per_xact;
ControlFile->wal_level = wal_level;
+ ControlFile->wal_log_hintbits = walLogHintbits;
UpdateControlFile();
}
}
***************
*** 9343,9348 **** xlog_redo(XLogRecPtr lsn, XLogRecord *record)
--- 9348,9354 ----
ControlFile->max_prepared_xacts = xlrec.max_prepared_xacts;
ControlFile->max_locks_per_xact = xlrec.max_locks_per_xact;
ControlFile->wal_level = xlrec.wal_level;
+ ControlFile->wal_log_hintbits = walLogHintbits;
/*
* Update minRecoveryPoint to ensure that if recovery is aborted, we
*** a/src/backend/postmaster/postmaster.c
--- b/src/backend/postmaster/postmaster.c
***************
*** 817,822 **** PostmasterMain(int argc, char *argv[])
--- 817,825 ----
if (XLogArchiveMode && wal_level == WAL_LEVEL_MINIMAL)
ereport(ERROR,
(errmsg("WAL archival (archive_mode=on) requires wal_level \"archive\" or \"hot_standby\"")));
+ if (walLogHintbits && wal_level == WAL_LEVEL_MINIMAL)
+ ereport(ERROR,
+ (errmsg("Logging of hint bits (wal_log_hintbits = on) requires wal_level \"archive\" or \"hot_standby\"")));
if (max_wal_senders > 0 && wal_level == WAL_LEVEL_MINIMAL)
ereport(ERROR,
(errmsg("WAL streaming (max_wal_senders > 0) requires wal_level \"archive\" or \"hot_standby\"")));
*** a/src/backend/storage/buffer/bufmgr.c
--- b/src/backend/storage/buffer/bufmgr.c
***************
*** 2626,2633 **** MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
bool delayChkpt = false;
/*
! * If checksums are enabled, and the buffer is permanent, then a full
! * page image may be required even for some hint bit updates to
* protect against torn pages. This full page image is only necessary
* if the hint bit update is the first change to the page since the
* last checkpoint.
--- 2626,2633 ----
bool delayChkpt = false;
/*
! * If checksums or logging of hint bits are enabled, and the buffer is permanent,
! * then a full page image may be required even for some hint bit updates to
* protect against torn pages. This full page image is only necessary
* if the hint bit update is the first change to the page since the
* last checkpoint.
***************
*** 2635,2641 **** MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
* We don't check full_page_writes here because that logic is included
* when we call XLogInsert() since the value changes dynamically.
*/
! if (DataChecksumsEnabled() && (bufHdr->flags & BM_PERMANENT))
{
/*
* If we're in recovery we cannot dirty a page because of a hint.
--- 2635,2641 ----
* We don't check full_page_writes here because that logic is included
* when we call XLogInsert() since the value changes dynamically.
*/
! if ((DataChecksumsEnabled() || walLogHintbits) && (bufHdr->flags & BM_PERMANENT))
{
/*
* If we're in recovery we cannot dirty a page because of a hint.
*** a/src/backend/utils/misc/guc.c
--- b/src/backend/utils/misc/guc.c
***************
*** 854,859 **** static struct config_bool ConfigureNamesBool[] =
--- 854,870 ----
true,
NULL, NULL, NULL
},
+
+ {
+ {"wal_log_hintbits", PGC_POSTMASTER, WAL_SETTINGS,
+ gettext_noop("Writes hint bits log to WAL when first updated after a checkpoint"),
+ NULL
+ },
+ &walLogHintbits,
+ false,
+ NULL, NULL, NULL
+ },
+
{
{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
gettext_noop("Logs each checkpoint."),
*** a/src/backend/utils/misc/postgresql.conf.sample
--- b/src/backend/utils/misc/postgresql.conf.sample
***************
*** 181,186 ****
--- 181,187 ----
# fsync_writethrough
# open_sync
#full_page_writes = on # recover from partial page writes
+ #wal_log_hintbits = off # turns logging of WAL when updating hint bits
#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers
# (change requires restart)
#wal_writer_delay = 200ms # 1-10000 milliseconds
*** a/src/bin/pg_controldata/pg_controldata.c
--- b/src/bin/pg_controldata/pg_controldata.c
***************
*** 291,295 **** main(int argc, char *argv[])
--- 291,297 ----
(ControlFile.float8ByVal ? _("by value") : _("by reference")));
printf(_("Data page checksum version: %u\n"),
ControlFile.data_checksum_version);
+ printf(_("Wal log hintbits: %u\n"),
+ ControlFile.wal_log_hintbits);
return 0;
}
*** a/src/include/access/xlog.h
--- b/src/include/access/xlog.h
***************
*** 189,194 **** extern bool XLogArchiveMode;
--- 189,195 ----
extern char *XLogArchiveCommand;
extern bool EnableHotStandby;
extern bool fullPageWrites;
+ extern bool walLogHintbits;
extern bool log_checkpoints;
extern int num_xloginsert_slots;
*** a/src/include/access/xlog_internal.h
--- b/src/include/access/xlog_internal.h
***************
*** 209,214 **** typedef struct xl_parameter_change
--- 209,215 ----
int max_prepared_xacts;
int max_locks_per_xact;
int wal_level;
+ bool wal_log_hintbits;
} xl_parameter_change;
/* logs restore point */
*** a/src/include/catalog/pg_control.h
--- b/src/include/catalog/pg_control.h
***************
*** 219,224 **** typedef struct ControlFileData
--- 219,227 ----
/* CRC of all above ... MUST BE LAST! */
pg_crc32 crc;
+
+ /* Enable logging WAL when updating hint bits */
+ bool wal_log_hintbits;
} ControlFileData;
/*