Allow the wal_buffers setting to be auto-tuned to a reasonable value.
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Jan 2011 01:31:24 +0000 (20:31 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 23 Jan 2011 01:31:24 +0000 (20:31 -0500)
If wal_buffers is initially set to -1 (which is now the default), it's
replaced by 1/32nd of shared_buffers, with a minimum of 8 (the old default)
and a maximum of the XLOG segment size.  The allowed range for manual
settings is still from 4 up to whatever will fit in shared memory.

Greg Smith, with implementation correction by me.

doc/src/sgml/config.sgml
src/backend/access/transam/xlog.c
src/backend/utils/misc/guc.c
src/backend/utils/misc/postgresql.conf.sample

index 8e2a2c5d73685aa4b6bd61d2fe88232008601804..570c7c3b7de3b339eef4063823f94c892e32ca39 100644 (file)
@@ -1638,12 +1638,25 @@ SET ENABLE_SEQSCAN TO OFF;
       </indexterm>
       <listitem>
        <para>
-        The amount of memory used in shared memory for WAL data.  The
-        default is 64 kilobytes (<literal>64kB</>).  The setting need only
-        be large enough to hold the amount of WAL data generated by one
-        typical transaction, since the data is written out to disk at
-        every transaction commit.  This parameter can only be set at server
-        start.
+        The amount of shared memory used for WAL data that has not yet been
+        written to disk.  The default setting of -1 selects a size equal to
+        1/32nd (about 3%) of <xref linkend="guc-shared-buffers">, but not less
+        than <literal>64kB</literal> nor more than the size of one WAL
+        segment, typically <literal>16MB</literal>.  This value can be set
+        manually if the automatic choice is too large or too small,
+        but any positive value less than <literal>32kB</literal> will be
+        treated as <literal>32kB</literal>.
+        This parameter can only be set at server start.
+       </para>
+
+       <para>
+        The contents of the WAL buffers are written out to disk at every
+        transaction commit, so extremely large values are unlikely to
+        provide a significant benefit.  However, setting this value to at
+        least a few megabytes can improve write performance on a busy
+        server where many clients are committing at once.  The auto-tuning
+        selected by the default setting of -1 should give reasonable
+        results in most cases.
        </para>
 
        <para>
index 5b6a2302b19f3b6f21fbdc645aaa793b4d0409b3..85b2dcae070e020bad2cb90ba277e02cb6bc9769 100644 (file)
@@ -69,7 +69,7 @@
 /* User-settable parameters */
 int                    CheckPointSegments = 3;
 int                    wal_keep_segments = 0;
-int                    XLOGbuffers = 8;
+int                    XLOGbuffers = -1;
 int                    XLogArchiveTimeout = 0;
 bool           XLogArchiveMode = false;
 char      *XLogArchiveCommand = NULL;
@@ -4777,6 +4777,41 @@ GetSystemIdentifier(void)
        return ControlFile->system_identifier;
 }
 
+/*
+ * Auto-tune the number of XLOG buffers.
+ *
+ * If the user-set value of wal_buffers is -1, we auto-tune to about 3% of
+ * shared_buffers, with a maximum of one XLOG segment and a minimum of 8
+ * blocks (8 was the default value prior to PostgreSQL 9.1, when auto-tuning
+ * was added).  We also clamp manually-set values to at least 4 blocks; prior
+ * to PostgreSQL 9.1, a minimum of 4 was enforced by guc.c, but since that
+ * is no longer possible, we just silently treat such values as a request for
+ * the minimum.
+ */
+static void
+XLOGTuneNumBuffers(void)
+{
+       int                     xbuffers = XLOGbuffers;
+       char            buf[32];
+
+       if (xbuffers == -1)
+       {
+               xbuffers = NBuffers / 32;
+               if (xbuffers > XLOG_SEG_SIZE / XLOG_BLCKSZ)
+                       xbuffers = XLOG_SEG_SIZE / XLOG_BLCKSZ;
+               if (xbuffers < 8)
+                       xbuffers = 8;
+       }
+       else if (xbuffers < 4)
+               xbuffers = 4;
+
+       if (xbuffers != XLOGbuffers)
+       {
+               snprintf(buf, sizeof(buf), "%d", xbuffers);
+               SetConfigOption("wal_buffers", buf, PGC_POSTMASTER, PGC_S_OVERRIDE);
+       }
+}
+
 /*
  * Initialization of shared memory for XLOG
  */
@@ -4785,6 +4820,10 @@ XLOGShmemSize(void)
 {
        Size            size;
 
+       /* Figure out how many XLOG buffers we need. */
+       XLOGTuneNumBuffers();
+       Assert(XLOGbuffers > 0);
+
        /* XLogCtl */
        size = sizeof(XLogCtlData);
        /* xlblocks array */
index ffff60155966c52402c4d47d18084c7bb0b251ca..73b9f1b01ca7ddfdd7b31a29d4e939d2d91e911b 100644 (file)
@@ -1765,7 +1765,7 @@ static struct config_int ConfigureNamesInt[] =
                        GUC_UNIT_XBLOCKS
                },
                &XLOGbuffers,
-               8, 4, INT_MAX, NULL, NULL
+               -1, -1, INT_MAX, NULL, NULL
        },
 
        {
index f436b834680d3b3f0d8e9d5aeea3f7bdb55d05d6..6c6f9a9a0d858ebca2673f9c5e3ba0eae0fd83da 100644 (file)
                                        #   fsync_writethrough
                                        #   open_sync
 #full_page_writes = on                 # recover from partial page writes
-#wal_buffers = 64kB                    # min 32kB
+#wal_buffers = -1                      # min 32kB, -1 sets based on shared_buffers
                                        # (change requires restart)
 #wal_writer_delay = 200ms              # 1-10000 milliseconds