可靠性是任何嚴肅的資料系統的重要需求之一,而 PostgreSQL 盡一切可能保證可靠的操作。可靠操作的一個面向是,已提交事務記錄的所有資料都應該儲存在高可靠性的設備中,這樣可以防止斷電,作業系統故障和硬體故障(當然,高可靠度設備本身的故障除外)。通常,成功將資料寫入主機的永久性儲存(磁碟設備或等效設備)即可滿足此要求。 實際上,即使一台主機受到了致命的損壞,如果磁碟設備倖免於難,也可以將它們移動到具有類似硬體的另一台主機上,並且所有已提交的事務會保持不變。
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. First, there is the operating system's buffer cache, which caches frequently requested disk blocks and combines disk writes. Fortunately, all operating systems give applications a way to force writes from the buffer cache to disk, and PostgreSQL uses those features. (See the wal_sync_method parameter to adjust how this is done.)
Next, there might be a cache in the disk drive controller; this is particularly common on RAID controller cards. Some of these caches are write-through, meaning writes are sent to the drive as soon as they arrive. Others are write-back, meaning data is sent to the drive at 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-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.
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 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. Many solid-state drives (SSD) also have volatile write-back caches.
These caches can typically be disabled; however, the method for doing this varies by operating system and drive type:
On Linux, IDE and SATA drives can be queried using hdparm -I
; write caching is enabled if there is a *
next to Write cache
. hdparm -W 0
can be used to turn off write caching. SCSI drives can be queried using sdparm. Use sdparm --get=WCE
to check whether the write cache is enabled and sdparm --clear=WCE
to disable it.
On FreeBSD, IDE drives can be queried using atacontrol
and write caching turned off using hw.ata.wc=0
in /boot/loader.conf
; SCSI drives can be queried using camcontrol identify
, and the write cache both queried and changed using sdparm
when available.
On Solaris, the disk write cache is controlled by format -e
. (The Solaris ZFS file system is safe with disk write-cache enabled because it issues its own disk cache flush commands.)
On Windows, if wal_sync_method
is 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, write caching can be prevented by setting wal_sync_method
to fsync_writethrough
.
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 controller cache to the disks, eliminating much of the benefit of the BBU. You can run the pg_test_fsync program to see if you are affected. If you are affected, the performance benefits 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 functional; a faulty battery can potentially lead to data loss. Hopefully file system and disk controller designers will eventually address this suboptimal behavior.
When the operating system sends a write request to the storage hardware, there is little it can do to make sure the data has arrived at a truly non-volatile storage area. Rather, it is the administrator's responsibility to make certain that all storage components ensure integrity for both data and file-system metadata. 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
.
Another risk of data loss is posed by the disk platter write 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 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 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 from WAL. If you have file-system software that prevents partial page writes (e.g., ZFS), you can turn off this page imaging by turning off the full_page_writes parameter. Battery-Backed Unit (BBU) disk controllers do not prevent partial page writes unless they guarantee that data is written to the BBU as full (8kB) pages.
PostgreSQL also protects against some kinds of data corruption on storage devices that may occur because of hardware errors or media failure over time, such as reading/writing garbage data.
Each individual record in a WAL file is protected by a CRC-32 (32-bit) check that allows us to tell if record contents are correct. The CRC value is set when we write each WAL record and checked during crash recovery, archive recovery and replication.
Data pages are not currently checksummed by default, though full page images recorded in WAL records will be protected; see initdb for details about enabling data page checksums.
Internal data structures such as pg_xact
, pg_subtrans
, pg_multixact
, pg_serial
, pg_notify
, pg_stat
, pg_snapshots
are not directly checksummed, nor are pages protected by full page writes. However, where such data structures are persistent, WAL records are written that allow recent changes to be accurately rebuilt at crash recovery and those WAL records are protected as discussed above.
Individual state files in pg_twophase
are protected by CRC-32.
Temporary data files used in larger SQL queries for sorts, materializations and intermediate results are not currently checksummed, nor will WAL records be written for changes to those files.
PostgreSQL does not protect against correctable memory errors and it is assumed you will operate using RAM that uses industry standard Error Correcting Codes (ECC) or better protection.