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