PostgreSQL配置文件--WAL

3 WAL WRITE AHEAD LOG

3.1 Settings

3.1.1 fsync

字符串
默认: fsync = on   
开启后强制把数据同步更新到磁盘,可以保证数据库将在OS或者硬件崩溃的后恢复到一个一致的状态。
虽然关闭,可以提升数据库性能,但无法保证数据库崩溃后数据一致性。
通常情况下需要打开这个参数,除非能经受掉电或硬件故障带来的数据丢失,否则不要关闭。

3.1.2 wal_level

字符型
默认: wal_level = replica ,minimal、replica、logical三选一
重启数据库生效
预写日志模式
minimal是仅写入崩溃或者突发关机时所需要的信息
replica增加wal归档信息,包括只读服务器需要的信息。(9.6中新增,将之前版本的 archive 和 hot_standby 合并)
logical主要用于logical decoding场景
在写入频繁的场景中,会产生大量的WAL日志,而且WAL日志量会远远超过实际更新的数据量。叫做“WAL写放大”。
造成WAL写放大的主要原因有2点。
    1、在checkpoint之后第一次修改页面,需要在WAL中输出整个page,即全页写(full page writes)。全页写的目的是防止在意外宕机时出现的数据块部分写导致数据库无法恢复。
    2、更新记录时如果新记录位置(ctid)发生变更,索引记录也要相应变更,这个变更也要记入WAL。更严重的是索引记录的变更又有可能导致索引页的全页写,进一步加剧了WAL写放大。
过量的WAL输出会对系统资源造成很大的消耗,因此需要进行适当的优化。
    1. 磁盘IO:WAL写入是顺序写,通常再差的硬盘对付WAL的写入速度也是绰绰有余。所以一般可以忽略。
    2. 网络IO:对局域网内的复制估计还不算问题,远程复制就难说了。
    3. 磁盘空间:如果做WAL归档,需要的磁盘空间也是巨大的。 
版本小于或等于9.6的配置为:
    minimal是仅写入崩溃或者突发关机时所需要的信息(不建议使用)。
    archive是增加wal归档所需的日志(最常用)。
    hot_standby是在备用服务器上增加了运行只读查询所需的信息,一般实在流复制的时候使用到。

3.1.3 wal_buffers

数字型
默认: wal_buffers = -1 ,最小值32kB,-1表示和shared_buffers共用。
重启数据库生效

用于存放WAL数据的内存空间(日志缓存区的大小)。最小32K。
执行一个大事务肯定受到影响,应该适当的增大该参数,降低IO。
如果比较多的并发短事务,应该考了设置commit_delay、commit_siblings。

3.1.4 wal_writer_delay

数字型
默认: wal_writer_delay = 200ms ,取值范围1-10000ms
重启数据库生效

WAL writer进程的间歇时间。决定写事务日志进程的睡眠时间。默认值是200ms。
WAL进程每次在完成写事务日志的任务后,就会等待wal_writer_delay时间,然后将新产生的事务日志从缓冲区写到WAL文件中。
准确的配置应该根据自身系统的运行状况。
    如果时间过长可能造成WAL buffer的内存不足,数据丢失的危险;
    反之过小将会引起WAL的不断的写入,对磁盘的IO也是很大考验。

3.1.5 wal_sync_method

字符串
默认: wal_sync_method = fdatasync ,open_datasync、fdatasync(default on Linux)、fsync_writethrough、fsync、open_sync五选一   
wal_sync_method:
WAL写入磁盘的控制方式。
一般采用默认值即可,对于裸设备或文件系统的可选配置,在实际的使用中所带来的方便相对fsync很有限。

3.1.6 synchronous_commit

字符串
默认: synchronous_commit = on ,off、local、remote_write、remote_apply、on五选一       

控制事务提交后返回客户端是否成功的策略,可选值为:on、remote_write、local、off。默认值是ON。
当为on时还要看是否有同步备库,因此为on时表现如下:
    为on且没有开启同步备库时,会当wal日志真正刷新到磁盘永久存储后才会返回客户端事务已提交成功。
    当为on且开启了同步备库时(设置了synchronous_standby_names),必须要等事务日志刷新到本地磁盘,并且还要等远程备库也提交到磁盘才能返回客户端已经提交

off:写到缓存中就会向客户端返回提交成功。
    延迟写入磁盘的时间为最大3倍的wal_writer_delay参数的(默认200ms)的时间,关闭synchronous_commit会造成最多600ms的事务丢失,但对高并发的小事务系统来说,性能来说提升较大。

remote_write:当事务提交时,不仅要把wal刷新到磁盘,还需要等wal日志发送到备库操作系统(但不用等备库刷新到磁盘)。
    因此如果备库此时发生实例中断不会有数据丢失,因为数据还在操作系统上,而如果操作系统故障,则此部分wal日志还没有来得及写入磁盘就会丢失,备库启动后还需要想主库索取wal日志。

local:当事务提交时,仅写入本地磁盘即可返回客户端事务提交成功,而不管是否有同步备库。

如果没有同步备库,则on/remote_write/local都是一样的,仅等待事务刷新到本地磁盘。
因参数只是控制事务的状态反馈,因此对于数据的一致性不存在风险。但事务的状态信息影响着数据库的整个状态。
对于业务没有严谨要求的事务可以配置为OFF,能够为系统的性能带来不小的提升。
如果磁盘的IOPS一般,建议使用异步提交来提高性能,但是数据库crash或操作系统crash时,最多可能丢失2*wal_writer_delay时间段产生的事务日志(在wal buffer中) 

还可以局部设置,当有临时批量任务时可以这样设置:
    SET LOCAL synchronous_commit TO OFF;
这样局部事务可向备库异步的方式同步,而其他重要的事务以同步的方式向备库同步。

3.1.7 full_page_writes

布尔型
默认: full_page_writes = on ,off、on二选一 
重启数据库生效

是否开启全页写入,此参数是为了防止块折断的一种策略。
关于块折断,每种数据库都会遇到这样的问题,起因是:
    linux文件系统一个块(简称OS块)一般是4k,而数据库则一般是一个块8k。
    当数据库的脏块刷新到磁盘上时,由于底层是两个块组成的。
    比如刷第一个OS块到磁盘上了,而当刷第二个OS块的时候发生了停电等突然停机事故,则就发生了块折断。
    数据块是否折断是根据块的checksum值来检查的。

为了避免这种事故,pg的机制:
    将前滚和回滚所需的数据都写入到了WAL。如果不将整个page写入WAL中,在介质恢复时WAL中记录数据不足以实现完整的恢复。
    当checkpoint后的一个块第一次变脏后就要整块写入到wal日志中,后续继续修改此块则只把修改的信息写入wal日志中。
    如果在此过程中发生了停电,则实例启动后会从checkpoint检查点,之后开始进行实例恢复。
    如果有块折断,则在全页写入的块为基础进行恢复,最后覆盖磁盘上的折断块。
    所以当每次checkpoint后如果数据有修改都会进行全页写入,因此控制checkpoint的间隔是否重要。
    如果checkpoint_segments设置太小就会造成频繁的checkpoint,进而导致写入了过多的全页。

mysql为了防止块折断采用了double write,oracle采用了redo+undo机制,其中undo记录了前镜像,而redo则既记录了修改数据又记录了undo块。

on可以提高数据库的可靠性,减少数据丢失的概率,但是会产生过多的事务日志,降低数据库的性能。
支持原子写超过BLOCK_SIZE的块设备,在对齐后可以关闭。或者支持cow的文件系统可以关闭。

3.1.8 wal_compression

布尔型
默认: wal_compression = off
enable compression of full-page writes
如果是checkpoint后第一次修改页面,则输出整个page的内容(即full page image,简称FPI)。
是否对full-page writes数据进行压缩(即去掉page中没有数据的hole部分)写入。 

3.1.9 commit_delay

数字型
默认: commit_delay = 0 ,取值范围0-100000, 单位ms

至少有commit_siblings个并发事务时,该事务提交后,wal日志将延迟commit_delay时间后再写入磁盘。
可以合并其他事务进行组提交,所有当有大量事务的时候会延迟,而如果事务很稀少就不会再被延迟了。
单位ms,默认值是0,不用延迟。
非0值的影响:
    减少IO,提高性能:事务执行commit后不会立即写入磁盘,而存放在WAL buffer中
    崩溃数据面临着丢失的危险
    可能引起WAL buffer内存不足,尤其是提交事务较多的高峰期
个人建议采用默认值,同时将WAL文件存放在IO性能好的磁盘上。

3.1.10 commit_siblings

数字型
默认: commit_siblings = 5  ,取值范围0-100000

延迟提交wal日志的最小并发事务数,决定参数commit_delay是否生效。
假设值是5,表示数据库中正在执行的事务数大于或等于5,该事务提交后,wal日志将会存入wal buffer中,延迟commit_delay时间后再写入磁盘。
如果数据库中正在执行的事务数小于5,这个事务提交后将wal日志直接写入磁盘。

3.1.11 wal_writer_flush_after

wal write的字节数超过配置的阈值时,触发fsync。
IO很好的机器,不需要考虑平滑调度
默认值为1MB,如果设置为0,关闭该特性(9.6版本新增的参数)

3.1.12 其他

wal_log_hints = off                    # also do full page writes of non-critical updates

3.2 检查点 Checkpoints

3.2.1 checkpoint_timeout

数字型
默认: checkpoint_timeout = 5min ,取值范围30s-1h
重启数据库生效
数据库进行检查点操作的间隔。如果现在的时间减去上次检查点操作结束的时间超过了checkpoint_timeout的值,系统就会自动启动一个检查点操作。
不建议频繁做检查点,否则XLOG会产生很多的FULL PAGE WRITE(when full_page_writes=on),导致数据库崩溃以后需要较长时间恢复操作。

3.2.2 checkpoint_completion_target

浮点数
默认: checkpoint_completion_target = 0.5 ,取值范围0.0-1.0
控制检查点操作的执行时间。硬盘好的情况下,可以让检查点快速结束,恢复时也可以快速达到一致状态。
不要轻易地改变这个参数的值,使用默认值即可。
只能在postgresql.conf文件中被设置。

3.2.3 其他

max_wal_size = 1GB # 建议是SHARED BUFFER的2倍
min_wal_size = 80MB # 建议是max_wal_size/4
checkpoint_flush_after = 256kB         # measured in pages, 0 disables IO很好的机器,不需要考虑平滑调度, 否则建议128~256kB
checkpoint_warning = 30s               # 0 disables

3.3 归档 Archiving

3.3.1 archive_mode

布尔值
默认: archive_mode = off ,on和off二选一
重启数据库生效
对数据库进行周期备份,来防止数据的丢失,这就需要连续归档。
它不仅可以用于大型数据库的增量备份和恢复,也可以用于搭建standby镜像备份。
开启归档模式,主要涉及到三个参数:wal_level,archive_mode和archive_commandwal_level参数默认为mininal,设置此参数为archive或者之上的级别都可以打开归档。

3.3.2 archive_command

字符串
默认: archive_command = ''  , 占位符: %p=文件归档路径;%f=仅为文件名
重启数据库生效
当postgresql需要传输归档日志时,会调用archive_command指定的shell命令。
归档文件传输成功时,shell命令要返回0,此时,postgresql会认为归档文件已经传输成功,因此可以删除或者重新循环利用归档文件。
当shell命令返回非0值时,postgresql会保留所有未成功传输的归档日志,并不断尝试重新传输,直到成功。
如果归档命令一直不成功,pg_xlog目录会持续增长,有耗尽服务器存储空间的可能,此时postgresql会PANIC关闭,直到释放存储空间。
另外将归档WAL日志存储在本机上是风险极高,不被推荐的。
postgresql通过archive_command提供了存储WAL日志的灵活性,可以将归档日志存储到挂装的NFS目录,磁带,刻录到光盘,也可以将WAL日志通过ssh/scp,rsync传输到异机保存。 

3.3.3 archive_dir

字符串
默认: 在10版本的配置文件中找不到该配置
重启数据库生效
这个参数只有在启动数据库时,才能被设置。默认值是空串。它设定存放归档事务日志文件的目录。

3.3.4 archive_timeout

字符串
默认: archive_timeout = 0 , 单位是秒。0表示禁止
重启数据库生效
一般情况下,数据库只有在一个事务日志文件写满以后,才会切换到下一个事务日志文件。
让数据库在一个事务日志文件尚未写满的情况下切换到下一个事务日志文件。
值不是0,而且当前时间减去数据库上次进行事务日志文件切换的时间大于archive_timeout的值,数据库将进行一次事务日志文件切换。
原文地址:https://www.cnblogs.com/lykops/p/8263101.html