PostgreSQL checkpoint 相关参数优化设置与解释

1 minute read

背景

数据库的检查点相关参数如何配置,能让数据库运行更加顺滑?

内存、磁盘能力如何搭配,能发挥更好的性能?

OS的参数如何设置,能尽可能的降低大内存机器带来的IO风暴问题?

数据库检查点设置

假设服务器内存是512GB。磁盘顺序、随机写吞吐是2 GB/s。

1、经验值

shared_buffers = 128GB                  # 1/4 内存  
  
checkpoint_timeout = 30min              # range 30s-1d  
  
max_wal_size = 256GB          # 2*shared_buffers  
min_wal_size = 64GB           # shared_buffers * 1/2  
  
checkpoint_completion_target = 0.9     # checkpoint target duration, 0.0 - 1.0  

这里还没有考虑磁盘的读写能力。

因此可能经验值配置的参数会导致一些性能问题。

我们根据上面的设置,来计算一下数据库发生检查点时到底会产生多少IO。

1、以极端为例进行讲解。假设shared buffer所有页都是脏页。

那么有128 GB脏页。

另外两个参数控制平滑刷脏页的调度:

2、30分钟*0.9 的时间窗口内,要刷完所有脏页。也就是说超过时间后,CKPT进程会全速刷脏页,checkpoint进程不进行任何sleep。

3、在新产生 256GB * 0.9 的WAL一个周期内,要刷完所有脏页。也就是检查点开始后,产生的WAL如果超过了,CKPT进程会全速刷脏页,checkpoint进程不进行任何sleep。

开销计算

1、刷脏页开销,属于离散IO。

平均值: 128GB / (30600.9) = 80.9 MB/s

(实际是sleep调度的,峰值可能还会更高一些) 。 物理写。

2、业务产生的写WAL开销,属于顺序IO。

最大平均值: 256GB / (30*60) = 145.6 MB/s

(实际是sleep调度的,峰值可能还会更高一些) 。 物理写。

3、业务上写操作除了产生WAL,还有bgwriter(异步WRITER) 。 异步写。

最大平均值: 256GB / (30*60) = 145.6 MB/s (因为一个块可能被多次修改,但是writer此时可能更少) 。

4、操作系统merge IO(写bgwriter的DIRTY PAGE),离散大块IO。 物理写。

最大平均值: 256GB / (30*60) = 145.6 MB/s

因此最糟糕的情况下,以上述配置为例,检查点期间,数据库写操作吞吐均值可能是 80.9 MB/s + 145.6 MB/s + 145.6 MB/s = 372.1 MB/s。

这个值,结合磁盘能力,可以判断检查点是否会有磁盘瓶颈。

建议设置

由于业务上还需要读写磁盘,同时PG目前的版本还需要垃圾回收,FREEZE等会产生IO的操作。因此不能让计算得到的峰值与磁盘实际IO能力相当,应该有所保留。

1、磁盘IOPS指标,写吞吐。(假设给25%用作 刷脏离散写、WAL顺序写)

2、如果按经验参数,评估出来磁盘能力不足(检查点实际需要的IO能力,与磁盘厂商给出的IO能力的25%不匹配),怎么办?

首先调大checkpoint_timeout参数,如果到最大值(1 DAY),依旧无法满足,则需要降低shared_buffers,以及相应的max_wal_size。

3、建议设置 log_checkpoints=on , 可以评估checkpoint的统计信息,用于帮助修正以上参数。

操作系统刷脏页设置

大内存机器,LINUX可能会遇到IO HANG的问题,原因也是刷脏页的配置不正确。

LINUX也有刷脏页的内核配置,默认是一个百分比,10%的脏页,后台进程开始刷脏页。如果产生脏页过快,到达20%时,用户进程也会帮助刷脏页。

因此如果内存越大,这个阈值就越大,而如果磁盘能力没有跟上,可能一次性会刷几十GB的脏页,导致磁盘的IO能力打爆,影响正常业务。

相关参数

1、os 内核参数

vm.dirty_background_bytes = 409600000  
vm.dirty_background_ratio = 0  
vm.dirty_bytes = 0  
vm.dirty_expire_centisecs = 3000  
vm.dirty_ratio = 95  
vm.dirty_writeback_centisecs = 100  

2、数据库参数

shared_buffers = 8GB                    # min 128kB  
                                        # (change requires restart)  
  
# - Checkpoints -  
  
#checkpoint_timeout = 5min              # range 30s-1d  
#max_wal_size = 1GB  
#min_wal_size = 80MB  
#checkpoint_completion_target = 0.5     # checkpoint target duration, 0.0 - 1.0  
#checkpoint_flush_after = 256kB         # measured in pages, 0 disables  
#checkpoint_warning = 30s               # 0 disables  

小结

为了尽量的降低数据库检查点带来的IO突增,影响业务。应该根据磁盘IO能力来修正检查点设置的经验值,避免IO HANG的问题。

同时OS层面的道理也一样,要设置好对应的OS刷脏页的调度参数。

参考

《DBA不可不知的操作系统内核参数》

《PostgreSQL 检查点性能影响及源码分析 - 7》

《PostgreSQL 检查点性能影响及源码分析 - 6》

《PostgreSQL 检查点性能影响及源码分析 - 5》

《PostgreSQL 检查点性能影响及源码分析 - 4》

《PostgreSQL 检查点性能影响及源码分析 - 3》

《PostgreSQL 检查点性能影响及源码分析 - 2》

《PostgreSQL 检查点性能影响及源码分析 - 1》

《PostgreSQL 9.6 检查点柔性优化(SYNC_FILE_RANGE) - 在单机多实例下的IO Hang问题浅析与优化》

Flag Counter

digoal’s 大量PostgreSQL文章入口