]> granicus.if.org Git - postgresql/commitdiff
Force default wal_sync_method to be fdatasync on Linux.
authorTom Lane <tgl@sss.pgh.pa.us>
Thu, 9 Dec 2010 01:01:14 +0000 (20:01 -0500)
committerTom Lane <tgl@sss.pgh.pa.us>
Thu, 9 Dec 2010 01:01:14 +0000 (20:01 -0500)
Recent versions of the Linux system header files cause xlogdefs.h to
believe that open_datasync should be the default sync method, whereas
formerly fdatasync was the default on Linux.  open_datasync is a bad
choice, first because it doesn't actually outperform fdatasync (in fact
the reverse), and second because we try to use O_DIRECT with it, causing
failures on certain filesystems (e.g., ext4 with data=journal option).
This part of the patch is largely per a proposal from Marti Raudsepp.
More extensive changes are likely to follow in HEAD, but this is as much
change as we want to back-patch.

Also clean up confusing code and incorrect documentation surrounding the
fsync_writethrough option.  Those changes shouldn't result in any actual
behavioral change, but I chose to back-patch them anyway to keep the
branches looking similar in this area.

In 9.0 and HEAD, also do some copy-editing on the WAL Reliability
documentation section.

Back-patch to all supported branches, since any of them might get used
on modern Linux versions.

doc/src/sgml/config.sgml
doc/src/sgml/wal.sgml
src/backend/storage/file/fd.c
src/backend/utils/misc/postgresql.conf.sample
src/include/access/xlogdefs.h
src/include/port/linux.h
src/include/port/win32.h

index 65ac6fc5d2dee557d61ef3924740e55abf7bd07e..3284c70e22f546f3ae58cef670e79b2ba66163ce 100644 (file)
@@ -1459,18 +1459,19 @@ SET ENABLE_SEQSCAN TO OFF;
        <para>
         While turning off <varname>fsync</varname> is often a performance
         benefit, this can result in unrecoverable data corruption in
-        the event of an unexpected system shutdown or crash.  Thus it
-        is only advisable to turn off  <varname>fsync</varname> if
+        the event of a power failure or system crash.  Thus it
+        is only advisable to turn off <varname>fsync</varname> if
         you can easily recreate your entire database from external
         data.
        </para>
 
        <para>
         Examples of safe circumstances for turning off
-        <varname>fsync</varname> include the initial loading a new
+        <varname>fsync</varname> include the initial loading of a new
         database cluster from a backup file, using a database cluster
-        for processing statistics on an hourly basis which is then
-        recreated, or for a reporting read-only database clone which
+        for processing a batch of data after which the database
+        will be thrown away and recreated,
+        or for a read-only database clone which
         gets recreated frequently and is not used for failover.  High
         quality hardware alone is not a sufficient justification for
         turning off <varname>fsync</varname>.
@@ -1553,12 +1554,12 @@ SET ENABLE_SEQSCAN TO OFF;
         </listitem>
         <listitem>
         <para>
-         <literal>fsync_writethrough</> (call <function>fsync()</> at each commit, forcing write-through of any disk write cache)
+         <literal>fsync</> (call <function>fsync()</> at each commit)
         </para>
         </listitem>
         <listitem>
         <para>
-         <literal>fsync</> (call <function>fsync()</> at each commit)
+         <literal>fsync_writethrough</> (call <function>fsync()</> at each commit, forcing write-through of any disk write cache)
         </para>
         </listitem>
         <listitem>
@@ -1568,16 +1569,15 @@ SET ENABLE_SEQSCAN TO OFF;
         </listitem>
        </itemizedlist>
        <para>
-        Not all of these choices are available on all platforms.
         The <literal>open_</>* options also use <literal>O_DIRECT</> if available.
+        Not all of these choices are available on all platforms.
         The default is the first method in the above list that is supported
-        by the platform.  The default is not necessarily ideal; it might be
+        by the platform, except that <literal>fdatasync</> is the default on
+        Linux.  The default is not necessarily ideal; it might be
         necessary to change this setting or other aspects of your system
         configuration in order to create a crash-safe configuration or
         achieve optimal performance.
         These aspects are discussed in <xref linkend="wal-reliability">.
-        The utility <filename>src/tools/fsync</> in the PostgreSQL source tree
-        can do performance testing of various fsync methods.
         This parameter can only be set in the <filename>postgresql.conf</>
         file or on the server command line.
        </para>
index 8d8504552d2fbcf3bad35702b3201a7d5c4d4996..54fcf93954da608e6e9651882a58aebc8b673ab5 100644 (file)
@@ -27,7 +27,7 @@
   </para>
 
   <para>
-   While forcing data periodically to the disk platters might seem like
+   While forcing data to the disk platters periodically might seem like
    a simple operation, it is not. Because disk drives are dramatically
    slower than main memory and CPUs, several layers of caching exist
    between the computer's main memory and the disk platters.
@@ -48,7 +48,7 @@
    some later time. Such caches can be a reliability hazard because the
    memory in the disk controller cache is volatile, and will lose its
    contents in a power failure.  Better controller cards have
-   <firstterm>battery-backed unit</> (<acronym>BBU</>) caches, meaning
+   <firstterm>battery-backup units</> (<acronym>BBU</>s), meaning
    the card has a battery that
    maintains power to the cache in case of system power loss.  After power
    is restored the data will be written to the disk drives.
   <para>
    And finally, most disk drives have caches. Some are write-through
    while some are write-back, and the same concerns about data loss
-   exist for write-back drive caches as exist for disk controller
+   exist for write-back drive caches as for disk controller
    caches.  Consumer-grade IDE and SATA drives are particularly likely
-   to have write-back caches that will not survive a power failure,
-   though <acronym>ATAPI-6</> introduced a drive cache flush command
-   (<command>FLUSH CACHE EXT</>) that some file systems use, e.g.
-   <acronym>ZFS</>, <acronym>ext4</>.  (The SCSI command
-   <command>SYNCHRONIZE CACHE</> has long been available.) Many
-   solid-state drives (SSD) also have volatile write-back caches, and
-   many do not honor cache flush commands by default.
-  </para>
-
-  <para>
-   To check write caching on <productname>Linux</> use
-   <command>hdparm -I</>;  it is enabled if there is a <literal>*</> next
-   to <literal>Write cache</>; <command>hdparm -W</> to turn off
-   write caching.  On <productname>FreeBSD</> use
-   <application>atacontrol</>.  (For SCSI disks use <ulink
-   url="http://sg.danny.cz/sg/sdparm.html"><application>sdparm</></ulink>
-   to turn off <literal>WCE</>.)  On <productname>Solaris</> the disk
-   write cache is controlled by <ulink
-   url="http://www.sun.com/bigadmin/content/submitted/format_utility.jsp"><literal>format
-   -e</></ulink>. (The Solaris <acronym>ZFS</> file system is safe with
-   disk write-cache enabled because it issues its own disk cache flush
-   commands.)  On <productname>Windows</> if <varname>wal_sync_method</>
-   is <literal>open_datasync</> (the default), write caching is disabled
-   by unchecking <literal>My Computer\Open\{select disk
-   drive}\Properties\Hardware\Properties\Policies\Enable write caching on
-   the disk</>.  Also on Windows, <literal>fsync</> and
-   <literal>fsync_writethrough</> never do write caching.  The
-   <literal>fsync_writethrough</> option can also be used to disable
-   write caching on <productname>MacOS X</>.
-  </para>
-
-  <para>
-   Many file systems that use write barriers (e.g.  <acronym>ZFS</>,
-   <acronym>ext4</>) internally use <command>FLUSH CACHE EXT</> or
-   <command>SYNCHRONIZE CACHE</> commands to flush data to the platters on
-   write-back-enabled drives.  Unfortunately, such write barrier file
-   systems behave suboptimally when combined with battery-backed unit
+   to have write-back caches that will not survive a power failure.  Many
+   solid-state drives (SSD) also have volatile write-back caches.
+  </para>
+
+  <para>
+   These caches can typically be disabled; however, the method for doing
+   this varies by operating system and drive type:
+  </para>
+
+  <itemizedlist>
+    <listitem>
+      <para>
+        On <productname>Linux</>, IDE drives can be queried using
+        <command>hdparm -I</command>; write caching is enabled if there is
+        a <literal>*</> next to <literal>Write cache</>.  <command>hdparm -W</>
+        can be used to turn off write caching.  SCSI drives can be queried
+        using <ulink url="http://sg.danny.cz/sg/sdparm.html"><application>sdparm</></ulink>.
+        Use <command>sdparm --get=WCE</command> to check
+        whether the write cache is enabled and <command>sdparm --clear=WCE</>
+        to disable it.
+      </para>
+    </listitem>
+
+    <listitem>
+      <para>
+        On <productname>FreeBSD</>, IDE drives can be queried using
+        <command>atacontrol</command>, and SCSI drives using
+        <command>sdparm</command>.
+      </para>
+    </listitem>
+
+    <listitem>
+      <para>
+        On <productname>Solaris</>, the disk write cache is controlled by
+        <ulink url="http://www.sun.com/bigadmin/content/submitted/format_utility.jsp"><literal>format -e</></ulink>.
+        (The Solaris <acronym>ZFS</> file system is safe with disk write-cache
+        enabled because it issues its own disk cache flush commands.)
+      </para>
+    </listitem>
+
+    <listitem>
+      <para>
+        On <productname>Windows</>, if <varname>wal_sync_method</> is
+        <literal>open_datasync</> (the default), write caching can be disabled
+        by unchecking <literal>My Computer\Open\<replaceable>disk drive</>\Properties\Hardware\Properties\Policies\Enable write caching on the disk</>.
+        Alternatively, set <varname>wal_sync_method</varname> to
+        <literal>fsync</> or <literal>fsync_writethrough</>, which prevent
+        write caching.
+      </para>
+    </listitem>
+
+    <listitem>
+      <para>
+        On <productname>Mac OS X</productname>, write caching can be prevented by
+        setting <varname>wal_sync_method</> to <literal>fsync_writethrough</>.
+      </para>
+    </listitem>
+  </itemizedlist>
+
+  <para>
+   Recent SATA drives (those following <acronym>ATAPI-6</> or later)
+   offer a drive cache flush command (<command>FLUSH CACHE EXT</>),
+   while SCSI drives have long supported a similar command
+   <command>SYNCHRONIZE CACHE</>.  These commands are not directly
+   accessible to <productname>PostgreSQL</>, but some file systems
+   (e.g., <acronym>ZFS</>, <acronym>ext4</>) can use them to flush
+   data to the platters on write-back-enabled drives.  Unfortunately, such
+   file systems behave suboptimally when combined with battery-backup unit
    (<acronym>BBU</>) disk controllers.  In such setups, the synchronize
-   command forces all data from the BBU to the disks, eliminating much
-   of the benefit of the BBU.  You can run the utility
+   command forces all data from the controller cache to the disks,
+   eliminating much of the benefit of the BBU.  You can run the utility
    <filename>src/tools/fsync</> in the PostgreSQL source tree to see
    if you are affected.  If you are affected, the performance benefits
-   of the BBU cache can be regained by turning off write barriers in
+   of the BBU can be regained by turning off write barriers in
    the file system or reconfiguring the disk controller, if that is
    an option.  If write barriers are turned off, make sure the battery
-   remains active; a faulty battery can potentially lead to data loss.
+   remains functional; a faulty battery can potentially lead to data loss.
    Hopefully file system and disk controller designers will eventually
    address this suboptimal behavior.
   </para>
    ensure data integrity.  Avoid disk controllers that have non-battery-backed
    write caches.  At the drive level, disable write-back caching if the
    drive cannot guarantee the data will be written before shutdown.
+   If you use SSDs, be aware that many of these do not honor cache flush
+   commands by default.
    You can test for reliable I/O subsystem behavior using <ulink
    url="http://brad.livejournal.com/2116715.html"><filename>diskchecker.pl</filename></ulink>.
   </para>
    operations themselves. Disk platters are divided into sectors,
    commonly 512 bytes each.  Every physical read or write operation
    processes a whole sector.
-   When a write request arrives at the drive, it might be for 512 bytes,
-   1024 bytes, or 8192 bytes, and the process of writing could fail due
+   When a write request arrives at the drive, it might be for some multiple
+   of 512 bytes (<productname>PostgreSQL</> typically writes 8192 bytes, or
+   16 sectors, at a time), and the process of writing could fail due
    to power loss at any time, meaning some of the 512-byte sectors were
-   written, and others were not.  To guard against such failures,
+   written while others were not.  To guard against such failures,
    <productname>PostgreSQL</> periodically writes full page images to
    permanent WAL storage <emphasis>before</> modifying the actual page on
    disk. By doing this, during crash recovery <productname>PostgreSQL</> can
-   restore partially-written pages.  If you have a battery-backed disk
+   restore partially-written pages from WAL.  If you have a battery-backed disk
    controller or file-system software that prevents partial page writes
-   (e.g., ZFS),  you can turn off this page imaging by turning off the
+   (e.g., ZFS), you can safely turn off this page imaging by turning off the
    <xref linkend="guc-full-page-writes"> parameter.
   </para>
  </sect1>
index 89a2d4ae24afadda6138e92c6a5d38b3fbd4867e..613834eb96d47c71aa788a081a6e09f6b39fc72b 100644 (file)
@@ -257,12 +257,13 @@ static void RemovePgTempFilesInDir(const char *tmpdirname);
 int
 pg_fsync(int fd)
 {
-#ifndef HAVE_FSYNC_WRITETHROUGH_ONLY
-       if (sync_method != SYNC_METHOD_FSYNC_WRITETHROUGH)
-               return pg_fsync_no_writethrough(fd);
+       /* #if is to skip the sync_method test if there's no need for it */
+#if defined(HAVE_FSYNC_WRITETHROUGH) && !defined(FSYNC_WRITETHROUGH_IS_FSYNC)
+       if (sync_method == SYNC_METHOD_FSYNC_WRITETHROUGH)
+               return pg_fsync_writethrough(fd);
        else
 #endif
-               return pg_fsync_writethrough(fd);
+               return pg_fsync_no_writethrough(fd);
 }
 
 
index e1f5ab66ed56f19aac3f53ddda8f03d116044e86..a3880da7dac5d8ff55dc8f5f7a3f1fc8052627b0 100644 (file)
 #wal_sync_method = fsync               # the default is the first option 
                                        # supported by the operating system:
                                        #   open_datasync
-                                       #   fdatasync
+                                       #   fdatasync (default on Linux)
                                        #   fsync
                                        #   fsync_writethrough
                                        #   open_sync
index 0760b259308c627a9ad1603550db7e2f78fe4feb..1da1ae0db0c2d45b0a320ec404b124c9b04aeb69 100644 (file)
@@ -123,12 +123,12 @@ typedef uint32 TimeLineID;
 #endif
 #endif
 
-#if defined(OPEN_DATASYNC_FLAG)
+#if defined(PLATFORM_DEFAULT_SYNC_METHOD)
+#define DEFAULT_SYNC_METHOD            PLATFORM_DEFAULT_SYNC_METHOD
+#elif defined(OPEN_DATASYNC_FLAG)
 #define DEFAULT_SYNC_METHOD            SYNC_METHOD_OPEN_DSYNC
 #elif defined(HAVE_FDATASYNC)
 #define DEFAULT_SYNC_METHOD            SYNC_METHOD_FDATASYNC
-#elif defined(HAVE_FSYNC_WRITETHROUGH_ONLY)
-#define DEFAULT_SYNC_METHOD            SYNC_METHOD_FSYNC_WRITETHROUGH
 #else
 #define DEFAULT_SYNC_METHOD            SYNC_METHOD_FSYNC
 #endif
index 0f4432a4eff265ee2983c9c21165ed1ffd397c69..e2a4c4a114d5fd2910cd2451c2f6b42a6efbc5ef 100644 (file)
  * to have a kernel version test here.
  */
 #define HAVE_LINUX_EIDRM_BUG
+
+/*
+ * Set the default wal_sync_method to fdatasync.  With recent Linux versions,
+ * xlogdefs.h's normal rules will prefer open_datasync, which (a) doesn't
+ * perform better and (b) causes outright failures on ext4 data=journal
+ * filesystems, because those don't support O_DIRECT.
+ */
+#define PLATFORM_DEFAULT_SYNC_METHOD   SYNC_METHOD_FDATASYNC
index 7338b115c46884409a61479f5f5d044837c7535d..1473d9e8c3c3e546d47f396af1a8067e7c5d98e2 100644 (file)
 /* Must be here to avoid conflicting with prototype in windows.h */
 #define mkdir(a,b)     mkdir(a)
 
-#define HAVE_FSYNC_WRITETHROUGH
-#define HAVE_FSYNC_WRITETHROUGH_ONLY
 #define ftruncate(a,b) chsize(a,b)
+
+/* Windows doesn't have fsync() as such, use _commit() */
+#define fsync(fd) _commit(fd)
+
 /*
- *     Even though we don't support 'fsync' as a wal_sync_method,
- *     we do fsync() a few other places where _commit() is just fine.
+ * For historical reasons, we allow setting wal_sync_method to
+ * fsync_writethrough on Windows, even though it's really identical to fsync
+ * (both code paths wind up at _commit()).
  */
-#define fsync(fd) _commit(fd)
+#define HAVE_FSYNC_WRITETHROUGH
+#define FSYNC_WRITETHROUGH_IS_FSYNC
 
 #define USES_WINSOCK