diff --git a/configure b/configure index b5cdebb..6c7de66 100755 --- a/configure +++ b/configure @@ -816,7 +816,6 @@ enable_tap_tests with_blocksize with_segsize with_wal_blocksize -with_wal_segsize with_CC enable_depend enable_cassert @@ -1508,8 +1507,6 @@ Optional Packages: --with-segsize=SEGSIZE set table segment size in GB [1] --with-wal-blocksize=BLOCKSIZE set WAL block size in kB [8] - --with-wal-segsize=SEGSIZE - set WAL segment size in MB [16] --with-CC=CMD set compiler (deprecated) --with-tcl build Tcl modules (PL/Tcl) --with-tclconfig=DIR tclConfig.sh is in DIR @@ -3668,54 +3665,6 @@ cat >>confdefs.h <<_ACEOF #define XLOG_BLCKSZ ${XLOG_BLCKSZ} _ACEOF - -# -# WAL segment size -# -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for WAL segment size" >&5 -$as_echo_n "checking for WAL segment size... " >&6; } - - - -# Check whether --with-wal-segsize was given. -if test "${with_wal_segsize+set}" = set; then : - withval=$with_wal_segsize; - case $withval in - yes) - as_fn_error $? "argument required for --with-wal-segsize option" "$LINENO" 5 - ;; - no) - as_fn_error $? "argument required for --with-wal-segsize option" "$LINENO" 5 - ;; - *) - wal_segsize=$withval - ;; - esac - -else - wal_segsize=16 -fi - - -case ${wal_segsize} in - 1) ;; - 2) ;; - 4) ;; - 8) ;; - 16) ;; - 32) ;; - 64) ;; - *) as_fn_error $? "Invalid WAL segment size. Allowed values are 1,2,4,8,16,32,64." "$LINENO" 5 -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: ${wal_segsize}MB" >&5 -$as_echo "${wal_segsize}MB" >&6; } - - -cat >>confdefs.h <<_ACEOF -#define XLOG_SEG_SIZE (${wal_segsize} * 1024 * 1024) -_ACEOF - - # # C compiler # diff --git a/configure.in b/configure.in index 1d99cda..ea5d02e 100644 --- a/configure.in +++ b/configure.in @@ -344,33 +344,6 @@ AC_DEFINE_UNQUOTED([XLOG_BLCKSZ], ${XLOG_BLCKSZ}, [ ]) # -# WAL segment size -# -AC_MSG_CHECKING([for WAL segment size]) -PGAC_ARG_REQ(with, wal-segsize, [SEGSIZE], [set WAL segment size in MB [16]], - [wal_segsize=$withval], - [wal_segsize=16]) -case ${wal_segsize} in - 1) ;; - 2) ;; - 4) ;; - 8) ;; - 16) ;; - 32) ;; - 64) ;; - *) AC_MSG_ERROR([Invalid WAL segment size. Allowed values are 1,2,4,8,16,32,64.]) -esac -AC_MSG_RESULT([${wal_segsize}MB]) - -AC_DEFINE_UNQUOTED([XLOG_SEG_SIZE], [(${wal_segsize} * 1024 * 1024)], [ - XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 - and larger than XLOG_BLCKSZ (preferably, a great deal larger than - XLOG_BLCKSZ). - - Changing XLOG_SEG_SIZE requires an initdb. -]) - -# # C compiler # diff --git a/contrib/pg_standby/pg_standby.c b/contrib/pg_standby/pg_standby.c index e4d057e..7ed3522 100644 --- a/contrib/pg_standby/pg_standby.c +++ b/contrib/pg_standby/pg_standby.c @@ -33,9 +33,12 @@ #include "pg_getopt.h" #include "access/xlog_internal.h" +#include "access/xlogreader.h" const char *progname; +uint32 XLogSegSize; + /* Options and defaults */ int sleeptime = 5; /* amount of time to sleep between file checks */ int waittime = -1; /* how long we have been waiting, -1 no wait @@ -100,6 +103,54 @@ int nextWALFileType; struct stat stat_buf; +static bool SetWALFileNameForCleanup(void); + +/* Set XLogSegSize from the WAL file header */ +static bool +RetrieveXLogSegSize() +{ + int fd; + bool ret = false; + + if (stat(WALFilePath, &stat_buf) == 0) + { + if ((fd = open(WALFilePath, O_RDWR, 0)) >= 0) + { + char *buf = (char *) malloc(XLOG_BLCKSZ); + + if (read(fd, buf, XLOG_BLCKSZ) != XLOG_BLCKSZ) + { + fprintf(stderr, "could not read from log segment %s", + nextWALFileName); + fflush(stderr); + } + else + { + XLogPageHeader hdr = (XLogPageHeader) buf; + XLogLongPageHeader NewLongPage = (XLogLongPageHeader) hdr; + + XLogSegSize = NewLongPage->xlp_seg_size; + need_cleanup = SetWALFileNameForCleanup(); + + if (debug) + { + fprintf(stderr, + _("WAL segment size: %d \n"), NewLongPage->xlp_seg_size); + fprintf(stderr, "Keep archive history: "); + if (need_cleanup) + fprintf(stderr, "%s and later\n", exclusiveCleanupFileName); + else + fprintf(stderr, "no cleanup required\n"); + fflush(stderr); + } + ret = true; + } + } + close(fd); + } + return ret; +} + /* ===================================================================== * * Customizable section @@ -184,42 +235,47 @@ CustomizableNextWALFileReady(void) nextWALFileType = XLOG_BACKUP_LABEL; return true; } - else if (stat_buf.st_size == XLOG_SEG_SIZE) + else { + /* Check if we can read the WAL header and set the XLogSegSize */ + if (!RetrieveXLogSegSize()) + return false; + + if (stat_buf.st_size == XLOG_SEG_SIZE) + { #ifdef WIN32 - /* - * Windows 'cp' sets the final file size before the copy is - * complete, and not yet ready to be opened by pg_standby. So we - * wait for sleeptime secs before attempting to restore. If that - * is not enough, we will rely on the retry/holdoff mechanism. - * GNUWin32's cp does not have this problem. - */ - pg_usleep(sleeptime * 1000000L); + /* + * Windows 'cp' sets the final file size before the copy is + * complete, and not yet ready to be opened by pg_standby. So + * we wait for sleeptime secs before attempting to restore. If + * that is not enough, we will rely on the retry/holdoff + * mechanism. GNUWin32's cp does not have this problem. + */ + pg_usleep(sleeptime * 1000000L); #endif - nextWALFileType = XLOG_DATA; - return true; - } + nextWALFileType = XLOG_DATA; + return true; + } - /* - * If still too small, wait until it is the correct size - */ - if (stat_buf.st_size > XLOG_SEG_SIZE) - { - if (debug) + /* + * If still too small, wait until it is the correct size + */ + if (stat_buf.st_size > XLOG_SEG_SIZE) { - fprintf(stderr, "file size greater than expected\n"); - fflush(stderr); + if (debug) + { + fprintf(stderr, "file size greater than expected\n"); + fflush(stderr); + } + exit(3); } - exit(3); } } return false; } -#define MaxSegmentsPerLogFile ( 0xFFFFFFFF / XLOG_SEG_SIZE ) - static void CustomizableCleanupPriorWALFiles(void) { @@ -315,6 +371,7 @@ SetWALFileNameForCleanup(void) uint32 log_diff = 0, seg_diff = 0; bool cleanup = false; + int MaxSegmentsPerLogFile = (0xFFFFFFFF / XLogSegSize); if (restartWALFileName) { @@ -708,8 +765,6 @@ main(int argc, char **argv) CustomizableInitialize(); - need_cleanup = SetWALFileNameForCleanup(); - if (debug) { fprintf(stderr, "Trigger file: %s\n", triggerPath ? triggerPath : ""); @@ -721,11 +776,6 @@ main(int argc, char **argv) fprintf(stderr, "Max wait interval: %d %s\n", maxwaittime, (maxwaittime > 0 ? "seconds" : "forever")); fprintf(stderr, "Command for restore: %s\n", restoreCommand); - fprintf(stderr, "Keep archive history: "); - if (need_cleanup) - fprintf(stderr, "%s and later\n", exclusiveCleanupFileName); - else - fprintf(stderr, "no cleanup required\n"); fflush(stderr); } diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 69c599e..aad08de 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -562,7 +562,7 @@ tar -cf backup.tar /usr/local/pgsql/data produces an indefinitely long sequence of WAL records. The system physically divides this sequence into WAL segment files, which are normally 16MB apiece (although the segment size - can be altered when building PostgreSQL). The segment + can be altered during initdb). The segment files are given numeric names that reflect their position in the abstract WAL sequence. When not using WAL archiving, the system normally creates just a few segment files and then diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml index 568995c..5b975b4 100644 --- a/doc/src/sgml/installation.sgml +++ b/doc/src/sgml/installation.sgml @@ -1027,20 +1027,6 @@ su - postgres - - - - Set the WAL segment size, in megabytes. This is - the size of each individual file in the WAL log. It may be useful - to adjust this size to control the granularity of WAL log shipping. - The default size is 16 megabytes. - The value must be a power of 2 between 1 and 64 (megabytes). - Note that changing this value requires an initdb. - - - - - diff --git a/doc/src/sgml/ref/initdb.sgml b/doc/src/sgml/ref/initdb.sgml index d9faa96..f37ba61 100644 --- a/doc/src/sgml/ref/initdb.sgml +++ b/doc/src/sgml/ref/initdb.sgml @@ -316,6 +316,20 @@ PostgreSQL documentation + + + + Set the WAL segment size, in megabytes. This is + the size of each individual file in the WAL log. It may be useful + to adjust this size to control the granularity of WAL log shipping. + The default size is 16 megabytes. + The value must be a power of 2 between 1 and 1024 (megabytes). + Note that this value is fixed for the lifetime of the database cluster. + + + + + diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 1468ba5..08ff49d 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -752,13 +752,12 @@ WAL logs are stored in the directory pg_wal under the data directory, as a set of segment files, normally each 16 MB in size (but the size can be changed - by altering the