Force default wal_sync_method to be fdatasync on Linux.
authorTom Lane <[email protected]>
Thu, 9 Dec 2010 01:01:19 +0000 (20:01 -0500)
committerTom Lane <[email protected]>
Thu, 9 Dec 2010 01:01:19 +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
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 3aa74870f881e5d0ec9a5e2930d30eebb1713695..f32872196273f85f478f8b9b042471e80d033738 100644 (file)
@@ -1442,12 +1442,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>
@@ -1457,12 +1457,11 @@ 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 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.
index 7acc72f0d4bab5d5d43f4dff09f50c0e6033112b..5b7e60a4fd9bfdc216b19f5bfda9cf25e351f2f5 100644 (file)
@@ -256,12 +256,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 fabfc75f55d25d9f5adde115ac01a87a5a9e5a34..ae839c634f69e01061c55b5d75ac8e4e162afce9 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 f9426dc32648935e4e7b8fb0c7b67d33e2e032bd..2761deb476f25abd76ebce05f11f01fcb79e7299 100644 (file)
@@ -110,12 +110,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 b83dac93173bf081227d306545f5afaba5c7624f..8586bf106b03e6d60b06a2768e616ecc55e9921a 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