Postgres间隔大量写IO的解决办法
概述
为了保证数据可靠性,同时还要保证好的读写性能,以及读写的一致性,经过多年的积累,REDO日志,shared buffer等基本成为关系型数据库的标配。postgres也不例外。
为了保证数据的可靠性,通常在将脏页面写入硬盘前,先将wal日志先写入硬盘,然后将修改的数据异步分批写入。
为了保证好的读写性能,修改的数据先写到shared buffer中,而不是直接写入硬盘,因为数据页很离散(修改的数据分布在不同的表中)。数据库会把wal日志顺序写入硬盘中。
postgres提供两种方式写:write和fsync。区别是:
write:数据库会将buffer中的脏页根据写入策略将老化的脏页面写到OS,OS再根据自己的调度算法将脏页写入硬盘。
fsync:数据库直接调用OS的fsync函数,直接写入硬盘。
OS层面
涉及到几个内核参数,同时还涉及到文件系统。
dirty_background_ratio
设置方法
1、修改systctl:vm.dirty_background_ratio
2、修改文件/proc/sys/vm/dirty_background_ratio
含义
在尝试执行writeback操作(即OS触发background flush线程刷脏页)之前内存脏页面比例。
控制文件系统的pdflush进程,在何时刷新磁盘。
单位是百分比,当写缓冲使用到系统内存多少时,pdflush开始向磁盘写出数据。
增大之会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
但当需要持续、恒定的写入场合时,应该降低其数值。缺省值5。
dirty_expire_centisecs
设置方法
1、修改systctl:vm.dirty_writeback_centisecs
2、修改文件/proc/sys/vm/dirty_expire_centisecs
含义
background flush线程将存活时间超过该值的脏页刷盘(类似LRU)。
数据可以保持为dirty状态的最大时间,超过该值pdflush进程就开始考虑写到磁盘中去。
单位是1/100s。缺省30000,也就是30s。
对于特别重载的写操作来说,这个值适当缩小也是好的,但也不能缩小太多,因为缩小太多也会导致IO提高太快。
建议设置为1500,也就是15秒算旧。
dirty_ratio
设置方法
1、修改systctl:vm.dirty_ratio
2、修改文件/proc/sys/vm/dirty_ratio
含义
控制文件系统的文件系统写缓冲区的大小,单位是百分比。
当脏页比例达到该值,用户进程在调用write时,会触发flush磁盘的操作。表示当写缓冲使用到系统内存多少时,开始向磁盘写出数据。
当一个任务(或者进程)在脏页面过多的环境中执行文件写操作时,如果脏页面占用总内存的百分比高于dirty_ratio值,那么系统就执行脏页面写入硬盘操作。
增大会使用更多系统内存用于磁盘写缓冲,也可以极大提高系统的写性能。
但当需要持续、恒定的写入场合时,应该降低其数值,缺省值10。
dirty_writeback_centisecs
设置方法
1、修改systctl:vm.dirty_writeback_centisecs
2、修改文件/proc/sys/vm/dirty_writeback_centisecs
含义
控制内核的脏数据刷新进程pdflush的运行间隔,执行background flush线程的唤醒间隔。
单位是1/100s。缺省值是500,也就是5s。
适当减少该值有写操作削峰作用,如果系统是持续地写入动作,那么降低该值比较好,可以把尖峰写操作削平成多次写操作。
该参数值应小于dirty_expire_centisecs,但太小I/O太频繁,反而使系统性能下降。
据说1:6 (dirty_expire_centisecs: dirty_writeback_centisecs )的比例比较好。
dirty_background_bytes
如果内存非常大,当触发后台线程刷脏页时,可能需要刷很多脏页,导致尖锐的IO需求。
可以通过修改内核参数vm.dirtybackgroundbytes达到削尖的目的。
vm.dirtybackgroundbytes = 102400000 当脏页数达到了100MB,系统触发background flush线程刷脏页
数据库层面
wal日志写入方式fsync
fsync = on
开启后强制把wal日志同步更新到磁盘,可以保证数据库将在OS或者硬件崩溃的后恢复到一个一致的状态。
虽然关闭,可以提升数据库性能,但无法保证数据库崩溃后数据一致性。
通常情况下需要打开这个参数,除非能经受掉电或硬件故障带来的数据丢失,否则不要关闭。
backend_flush_after
单位:BLCKSZ
当某backend process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。
从而削减os dirty page堆积。
bgwriter_flush_after
单位:BLCKSZ
当bgwriter process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。
从而削减os dirty page堆积。
checkpoint_flush_after
单位:BLCKSZ
当checkpointer process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。
从而削减os dirty page堆积。
wal_writer_flush_after
单位:BLCKSZ
当wal writer process脏数据超过配置阈值时,触发调用OS sync_file_range,告诉os backend flush线程异步刷盘。
从而削减os dirty page堆积。