diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index f1d3ca2f09..8e2a2c5d73 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1460,18 +1460,19 @@ SET ENABLE_SEQSCAN TO OFF; While turning off fsync 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 fsync if + the event of a power failure or system crash. Thus it + is only advisable to turn off fsync if you can easily recreate your entire database from external data. Examples of safe circumstances for turning off - fsync include the initial loading a new + fsync 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 fsync. @@ -1554,12 +1555,12 @@ SET ENABLE_SEQSCAN TO OFF; - fsync_writethrough (call fsync() at each commit, forcing write-through of any disk write cache) + fsync (call fsync() at each commit) - fsync (call fsync() at each commit) + fsync_writethrough (call fsync() at each commit, forcing write-through of any disk write cache) @@ -1569,16 +1570,15 @@ SET ENABLE_SEQSCAN TO OFF; - Not all of these choices are available on all platforms. The open_* options also use 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 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 . - The utility src/tools/fsync in the PostgreSQL source tree - can do performance testing of various fsync methods. This parameter can only be set in the postgresql.conf file or on the server command line. @@ -1686,21 +1686,20 @@ SET ENABLE_SEQSCAN TO OFF; When the commit data for a transaction is flushed to disk, any additional commits ready at that time are also flushed out. commit_delay adds a time delay, set in - microseconds, before writing some commit records to the WAL - buffer and flushing the buffer out to disks. A nonzero delay - can allow more transactions to be committed with only one call - to the active wal_sync_method, if + microseconds, before a transaction attempts to + flush the WAL buffer out to disk. A nonzero delay can allow more + transactions to be committed with only one flush operation, if system load is high enough that additional transactions become ready to commit within the given interval. But the delay is just wasted if no other transactions become ready to commit. Therefore, the delay is only performed if at least commit_siblings other transactions are active at the instant that a server process has written its - commit record. The default is zero (no delay). Since - all pending commit data flushes are written at every flush - regardless of this setting, it is rare that adding delay to - that by increasing this parameter will actually improve commit - performance. + commit record. + The default commit_delay is zero (no delay). + Since all pending commit data will be written at every flush + regardless of this setting, it is rare that adding delay + by increasing this parameter will actually improve performance. diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index a2724fad6b..b44a6257ec 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -27,7 +27,7 @@ - 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 - battery-backed unit (BBU) caches, meaning + battery-backup units (BBUs), 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. @@ -57,15 +57,10 @@ 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 ATAPI-6 introduced a drive cache flush command - (FLUSH CACHE EXT) that some file systems use, e.g. - ZFS, ext4. (The SCSI 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. + to have write-back caches that will not survive a power failure. Many + solid-state drives (SSD) also have volatile write-back caches. @@ -81,7 +76,7 @@ a * next to Write cache. hdparm -W can be used to turn off write caching. SCSI drives can be queried using sdparm. - for SCSI drives. Use sdparm --get=WCE to check + Use sdparm --get=WCE to check whether the write cache is enabled and sdparm --clear=WCE to disable it. @@ -107,35 +102,40 @@ On Windows, if wal_sync_method is - open_datasync (the default), write caching is disabled - by unchecking My Computer\Open\{select disk drive}\Properties\Hardware\Properties\Policies\Enable write caching on the disk. - Alternatively, set wal_sync_method to fsync or fsync_writethrough, which never do write caching. + open_datasync (the default), write caching can be disabled + by unchecking My Computer\Open\disk drive\Properties\Hardware\Properties\Policies\Enable write caching on the disk. + Alternatively, set wal_sync_method to + fsync or fsync_writethrough, which prevent + write caching. - On MacOS X, write caching can be disabled by + On Mac OS X, write caching can be prevented by setting wal_sync_method to fsync_writethrough. - Many file systems that use write barriers (e.g. ZFS, - ext4) internally use FLUSH CACHE EXT or - 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 + Recent SATA drives (those following ATAPI-6 or later) + offer a drive cache flush command (FLUSH CACHE EXT), + while SCSI drives have long supported a similar command + SYNCHRONIZE CACHE. These commands are not directly + accessible to PostgreSQL, but some file systems + (e.g., ZFS, 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 (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 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. @@ -148,6 +148,8 @@ 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 diskchecker.pl. @@ -157,16 +159,17 @@ 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 (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, PostgreSQL periodically writes full page images to permanent WAL storage before modifying the actual page on disk. By doing this, during crash recovery 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 parameter. diff --git a/src/backend/storage/file/fd.c b/src/backend/storage/file/fd.c index fd5ec7805f..4f7dc39d63 100644 --- a/src/backend/storage/file/fd.c +++ b/src/backend/storage/file/fd.c @@ -260,12 +260,13 @@ static bool looks_like_temp_rel_name(const char *name); 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); } diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 80ee04d30a..f436b83468 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -157,7 +157,7 @@ #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 diff --git a/src/include/access/xlogdefs.h b/src/include/access/xlogdefs.h index 18b214e992..072096ddff 100644 --- a/src/include/access/xlogdefs.h +++ b/src/include/access/xlogdefs.h @@ -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 diff --git a/src/include/port/linux.h b/src/include/port/linux.h index b9498b239d..bcaa42dc4e 100644 --- a/src/include/port/linux.h +++ b/src/include/port/linux.h @@ -12,3 +12,11 @@ * 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 diff --git a/src/include/port/win32.h b/src/include/port/win32.h index 3417ab5e95..9c2ae4d60c 100644 --- a/src/include/port/win32.h +++ b/src/include/port/win32.h @@ -34,15 +34,19 @@ /* 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) -/* - * Even though we don't support 'fsync' as a wal_sync_method, - * we do fsync() a few other places where _commit() is just fine. - */ + +/* Windows doesn't have fsync() as such, use _commit() */ #define fsync(fd) _commit(fd) +/* + * 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 HAVE_FSYNC_WRITETHROUGH +#define FSYNC_WRITETHROUGH_IS_FSYNC + #define USES_WINSOCK /* defines for dynamic linking on Win32 platform */