postgresql wal日志参数浅析

之前一直没有认真的学习pg的wal日志相关的参数,发现对这一部分有些不清楚,结合文档又梳理了一遍,浅浅的记录一下,因为wal日志非常重要,并且对性能影响很大,在生产库上要小心调整。

1.fsync

fsync :控制wal日志刷新是否开启刷新到磁盘,此参数控制wal_sync_method参数的刷新方法,如果fsync为off,则wal_sync_method的方法是没有意义的,
如果没开启这个参数,则可能由于wal日志块没有刷新到磁盘永久存储而导致故障发生后实例出现块折断(oracle称其为block curruption)
2.synchronous_commit:
synchronous_commit:同步提交参数, 控制事务提交后返回客户端是否成功的策略,可选值为:on, remote_write, local, and off.当为on时还要看是否有同步备库,因此为on时表现如下:
2.1 为on且没有开启同步备库的时候,会当wal日志真正刷新到磁盘永久存储后才会返回客户端事务已提交成功,
2.2 当为on且开启了同步备库的时候(设置了synchronous_standby_names),必须要等事务日志刷新到本地磁盘,并且还要等远程备库也提交到磁盘才能返回客户端已经提交.
off:写到缓存中就会向客户端返回提交成功,但也不是一直不刷到磁盘,延迟写入磁盘,延迟的时间为最大3倍的wal_writer_delay参数的(默认200ms)的时间,所有如果即使关闭synchronous_commit,也只会造成最多600ms的事务丢失,此事务甚至包括已经提交的事务(会丢数据),但数据库确可以安全启动,不会发生块折断,只是丢失了部分数据,但对高并发的小事务系统来说,性能来说提升较大。
remote_write:当事务提交时,不仅要把wal刷新到磁盘,还需要等wal日志发送到备库操作系统(但不用等备库刷新到磁盘),因此如果备库此时发生实例中断不会有数据丢失,因为数据还在操作系统上,而如果操作系统故障,则此部分wal日志还没有来得及写入磁盘就会丢失,备库启动后还需要想主库索取wal日志。
local:当事务提交时,仅写入本地磁盘即可返回客户端事务提交成功,而不管是否有同步备库
另外需要注意的是,如果没有设置同步备库,则 on/remote_write/local都是一样的,仅等待事务刷新到本地磁盘.
而且此参数还可以局部设置,当有临时批量任务时可以这样设置:
 SET LOCAL synchronous_commit TO OFF;
 这样局部事务可向备库异步的方式同步,而其他重要的事务以同步的方式向备库同步。
3.wal_sync_method 
wal_sync_method :wal日志刷新方法,可选值为open_datasync/fdatasync/fsync/fsync_writethrough/open_sync
linux系统默认为fdatasync,以open开头的在某些系统上不支持
4.full_page_writes
full_page_writes: 是否开启全页写入,此参数是为了防止块折断的一种策略,关于块折断,每种数据库都会遇到这样的问题,起因是这样的:linux操作系统文件系统一个块一般是4k,而数据库则一般是一个块8k,当数据库的脏块刷新到磁盘上时,由于底层是两个块组成的,比如刷第一个操作系统块到磁盘上了,而当刷第二个操作系统块的时候发生了停电等突然停机事故,则就发生了块折断(数据块是否折断是根据块的checksum值来检查的),为了避免这种事故,pg采用了这样的机制:
当checkpoint后的一个块第一次变脏后就要整块写入到wal日志中,后续继续修改此块则只把修改的信息写入wal日志中,如果在此过程中发生了停电,则实例启动后会从checkpoint检查点,之后开始进行实例恢复,如果有块折断,则在全页写入的块为基础进行恢复,最后覆盖磁盘上的折断块,所以当每次checkpoint后如果数据有修改都会进行全页写入,因此控制checkpoint的
间隔是否重要,如果checkpoint_segments设置太小就会造成频繁的checkpoint,进而导致写入了过多的全页.mysql为了防止块折断采用了double write,oracle采用了redo+undo机制,其中undo记录了前镜像,而redo则既记录了修改数据又记录了undo块。
5.wal_buffers
wal_buffers :wal缓冲区,默认为-1,大小为1/32的shared_buffer,最小不少于64k,最大不大于一个wal_segment(默认16M大小),一般保持默认即可,因为过了wal_writer_delay(默认200ms)总会刷新清空此缓存,设置太大了也用不上.
6.wal_writer_delay
wal_writer_delay:前面已经说过,这有点类似oracle和mysql的1s定时写日志策略,每隔这么长时间就会刷wal日志缓冲区的数据,然后sleep,到点后再刷,如此循环往复.
7.commit_delay
commit_delay :提交的延迟时间,如果设置了此参数,则会commit后延迟一段时间再进行提交,此机制可以合并其他事务进而一起进行组提交,不过合并的事务数是有限制的,要至少有commit_siblings参数个事务等待提交的时候才会延迟,所有当有大量事务的时候会延迟,而如果事务很稀少就不会再被延迟了.
8.commit_siblings
commit_siblings :组提交个数的最少个数,此参数上面已经进行说明

Tagged: ,

Comments are closed.