aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorThomas Munro <tmunro@postgresql.org>2019-04-02 14:37:14 +1300
committerThomas Munro <tmunro@postgresql.org>2019-04-02 14:37:14 +1300
commit475861b2615dd63ae8431d811749a6f9a15bbfd6 (patch)
treedf88475a55eaa2bf359000628325d7b798f90521 /src
parent4b82664156c230b59607704506f5b0a32ef490a2 (diff)
downloadpostgresql-475861b2615dd63ae8431d811749a6f9a15bbfd6.tar.gz
postgresql-475861b2615dd63ae8431d811749a6f9a15bbfd6.zip
Add wal_recycle and wal_init_zero GUCs.
On at least ZFS, it can be beneficial to create new WAL files every time and not to bother zero-filling them. Since it's not clear which other filesystems might benefit from one or both of those things, add individual GUCs to control those two behaviors independently and make only very general statements in the docs. Author: Jerry Jelinek, with some adjustments by Thomas Munro Reviewed-by: Alvaro Herrera, Andres Freund, Tomas Vondra, Robert Haas and others Discussion: https://postgr.es/m/CACPQ5Fo00QR7LNAcd1ZjgoBi4y97%2BK760YABs0vQHH5dLdkkMA%40mail.gmail.com
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/transam/xlog.c97
-rw-r--r--src/backend/utils/misc/guc.c20
-rw-r--r--src/backend/utils/misc/postgresql.conf.sample2
-rw-r--r--src/include/access/xlog.h2
4 files changed, 88 insertions, 33 deletions
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index a181e33dd4d..c6ca96079c1 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -95,6 +95,8 @@ bool wal_log_hints = false;
bool wal_compression = false;
char *wal_consistency_checking_string = NULL;
bool *wal_consistency_checking = NULL;
+bool wal_init_zero = true;
+bool wal_recycle = true;
bool log_checkpoints = false;
int sync_method = DEFAULT_SYNC_METHOD;
int wal_level = WAL_LEVEL_MINIMAL;
@@ -3209,6 +3211,7 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
XLogSegNo max_segno;
int fd;
int nbytes;
+ int save_errno;
XLogFilePath(path, ThisTimeLineID, logsegno, wal_segment_size);
@@ -3248,39 +3251,61 @@ XLogFileInit(XLogSegNo logsegno, bool *use_existent, bool use_lock)
(errcode_for_file_access(),
errmsg("could not create file \"%s\": %m", tmppath)));
- /*
- * Zero-fill the file. We have to do this the hard way to ensure that all
- * the file space has really been allocated --- on platforms that allow
- * "holes" in files, just seeking to the end doesn't allocate intermediate
- * space. This way, we know that we have all the space and (after the
- * fsync below) that all the indirect blocks are down on disk. Therefore,
- * fdatasync(2) or O_DSYNC will be sufficient to sync future writes to the
- * log file.
- */
memset(zbuffer.data, 0, XLOG_BLCKSZ);
- for (nbytes = 0; nbytes < wal_segment_size; nbytes += XLOG_BLCKSZ)
+
+ pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
+ save_errno = 0;
+ if (wal_init_zero)
{
+ /*
+ * Zero-fill the file. With this setting, we do this the hard way to
+ * ensure that all the file space has really been allocated. On
+ * platforms that allow "holes" in files, just seeking to the end
+ * doesn't allocate intermediate space. This way, we know that we
+ * have all the space and (after the fsync below) that all the
+ * indirect blocks are down on disk. Therefore, fdatasync(2) or
+ * O_DSYNC will be sufficient to sync future writes to the log file.
+ */
+ for (nbytes = 0; nbytes < wal_segment_size; nbytes += XLOG_BLCKSZ)
+ {
+ errno = 0;
+ if (write(fd, zbuffer.data, XLOG_BLCKSZ) != XLOG_BLCKSZ)
+ {
+ /* if write didn't set errno, assume no disk space */
+ save_errno = errno ? errno : ENOSPC;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /*
+ * Otherwise, seeking to the end and writing a solitary byte is
+ * enough.
+ */
errno = 0;
- pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_WRITE);
- if ((int) write(fd, zbuffer.data, XLOG_BLCKSZ) != (int) XLOG_BLCKSZ)
+ if (pg_pwrite(fd, zbuffer.data, 1, wal_segment_size - 1) != 1)
{
- int save_errno = errno;
+ /* if write didn't set errno, assume no disk space */
+ save_errno = errno ? errno : ENOSPC;
+ }
+ }
+ pgstat_report_wait_end();
- /*
- * If we fail to make the file, delete it to release disk space
- */
- unlink(tmppath);
+ if (save_errno)
+ {
+ /*
+ * If we fail to make the file, delete it to release disk space
+ */
+ unlink(tmppath);
- close(fd);
+ close(fd);
- /* if write didn't set errno, assume problem is no disk space */
- errno = save_errno ? save_errno : ENOSPC;
+ errno = save_errno;
- ereport(ERROR,
- (errcode_for_file_access(),
- errmsg("could not write to file \"%s\": %m", tmppath)));
- }
- pgstat_report_wait_end();
+ ereport(ERROR,
+ (errcode_for_file_access(),
+ errmsg("could not write to file \"%s\": %m", tmppath)));
}
pgstat_report_wait_start(WAIT_EVENT_WAL_INIT_SYNC);
@@ -4049,14 +4074,19 @@ RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr)
XLogSegNo endlogSegNo;
XLogSegNo recycleSegNo;
- /*
- * Initialize info about where to try to recycle to.
- */
- XLByteToSeg(endptr, endlogSegNo, wal_segment_size);
- if (RedoRecPtr == InvalidXLogRecPtr)
- recycleSegNo = endlogSegNo + 10;
+ if (wal_recycle)
+ {
+ /*
+ * Initialize info about where to try to recycle to.
+ */
+ XLByteToSeg(endptr, endlogSegNo, wal_segment_size);
+ if (RedoRecPtr == InvalidXLogRecPtr)
+ recycleSegNo = endlogSegNo + 10;
+ else
+ recycleSegNo = XLOGfileslop(RedoRecPtr);
+ }
else
- recycleSegNo = XLOGfileslop(RedoRecPtr);
+ recycleSegNo = 0; /* keep compiler quiet */
snprintf(path, MAXPGPATH, XLOGDIR "/%s", segname);
@@ -4065,7 +4095,8 @@ RemoveXlogFile(const char *segname, XLogRecPtr RedoRecPtr, XLogRecPtr endptr)
* segment. Only recycle normal files, pg_standby for example can create
* symbolic links pointing to a separate archive directory.
*/
- if (endlogSegNo <= recycleSegNo &&
+ if (wal_recycle &&
+ endlogSegNo <= recycleSegNo &&
lstat(path, &statbuf) == 0 && S_ISREG(statbuf.st_mode) &&
InstallXLogFileSegment(&endlogSegNo, path,
true, recycleSegNo, true))
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c
index aa564d153a5..cd5a65be75b 100644
--- a/src/backend/utils/misc/guc.c
+++ b/src/backend/utils/misc/guc.c
@@ -1175,6 +1175,26 @@ static struct config_bool ConfigureNamesBool[] =
},
{
+ {"wal_init_zero", PGC_SUSET, WAL_SETTINGS,
+ gettext_noop("Writes zeroes to new WAL files before first use."),
+ NULL
+ },
+ &wal_init_zero,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
+ {"wal_recycle", PGC_SUSET, WAL_SETTINGS,
+ gettext_noop("Recycles WAL files by renaming them."),
+ NULL
+ },
+ &wal_recycle,
+ true,
+ NULL, NULL, NULL
+ },
+
+ {
{"log_checkpoints", PGC_SIGHUP, LOGGING_WHAT,
gettext_noop("Logs each checkpoint."),
NULL
diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample
index cccb5f145a2..9b15361403e 100644
--- a/src/backend/utils/misc/postgresql.conf.sample
+++ b/src/backend/utils/misc/postgresql.conf.sample
@@ -206,6 +206,8 @@
#wal_compression = off # enable compression of full-page writes
#wal_log_hints = off # also do full page writes of non-critical updates
# (change requires restart)
+#wal_init_zero = on # zero-fill new WAL files
+#wal_recycle = on # recycle WAL files
#wal_buffers = -1 # min 32kB, -1 sets based on shared_buffers
# (change requires restart)
#wal_writer_delay = 200ms # 1-10000 milliseconds
diff --git a/src/include/access/xlog.h b/src/include/access/xlog.h
index eb6c44649dc..2af938bfdcb 100644
--- a/src/include/access/xlog.h
+++ b/src/include/access/xlog.h
@@ -116,6 +116,8 @@ extern bool EnableHotStandby;
extern bool fullPageWrites;
extern bool wal_log_hints;
extern bool wal_compression;
+extern bool wal_init_zero;
+extern bool wal_recycle;
extern bool *wal_consistency_checking;
extern char *wal_consistency_checking_string;
extern bool log_checkpoints;