PostgreSQL checkpoint(检查点)参数设置

1.简介

  PostgreSQL是依靠预写日志(WAL)的数据库之一,所有的更改首先被写入一个日志(一个变化的流),然后再写入数据文件.这提高了数据的安全性,因为在崩溃的情况下,数据库会使用WAL执行恢复,从WAL读取更改并将其重新应用于数据文件.虽然这可能会使写入量增加一倍,但实际上可能会提高性能,用户只需要等待WAL(刷新到磁盘),而数据文件仅在内存中修改,然后在后台刷新. WAL写入本质上是顺序写入的,而对数据文件的写入往往是随机写入的.
  非常频繁的检查点(比如几秒一次).只保留少量的WAL,恢复速度非常快,但会将异步写入数据文件转换为同步数据文件,严重影响系统性能 (例如增加COMMIT延迟,降低吞吐量).因此在实践中,通常需要合理设置checkpoint_timeout和max_wal_size。
 

2.检查点触发原因

  • 直接执行CHECKPOINT命令
  • 执行需要检查点的命令(例如pg_start_backup,CREATE DATABASE或pg_ctl stop|restart等等)
  • 达到检查点配置时间(checkpoint_timeout)
  • max_wal_size已满("running out of WAL"或"filling WAL")
其中1和2和配置无关的,需要手动触发的事件
 

3.参数配置

(1)默认参数

checkpoint_timeout = 5min
# PostgreSQL 9.5之前是checkpoint_segments
max_wal_size = 1GB
checkpoint_segments和 max_wal_size之间的关系:
max_wal_size = (3 * checkpoint_segments) * 16MB
 

(2)checkpoint_timeout

  很难说checkpoint_timeout的"合理"值是什么,因为它取决于恢复时间(RTO),即可接受的最大恢复间是多少。因为checkpoint_timeout是生成WAL所需的时间,而不是恢复时间.WAL通常由多个进程生成,而恢复由单个进程执行,这不仅影响本地恢复,还会影响到具有流复制的备机。 当恢复文件系统缓存时,通常会在重新引导之后立即进行恢复。但一般来说,默认值(5分钟)相当低,普遍采用30分钟到1小时之间,PostgreSQL 9.6甚至增加了最多1天,建议使用30分钟。
checkpoint_timeout = 30min
 

(3)max_wal_size

  估计数据库在30分钟内产生多少WAL,以便我们可以使用max_wal_size.有以下几种方法来确定生成多少WAL:
  • 使用pg_current_xlog_insert_location()(pg9.x版本)或者select pg_current_wal_lsn()(pg10.x版本)查看实际的WAL位置
  • 启用log_checkpoints=on,然后从服务器日志中提取信息(每个完成的检查点将有详细的统计信息,包括WAL的数量)
计算max_wal_size
 
viid=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
3D/B4020A58
(1 row)

... 5分钟之后...

viid=# select pg_current_wal_lsn();
pg_current_wal_lsn
--------------------
3E/2203E0F8
(1 row)
viid=# select pg_wal_lsn_diff('3E/2203E0F8', '3D/B4020A58')/1024/1024/1024;
        ?column?
------------------------
1.7188622057437897
(1 row)
  这表明在5分钟内,数据库产生了1.8GB的WAL,所以对于checkpoint_timeout = 30min,大约10GB(30/5*1.8G)的WAL.但是如前所述max_wal_size是多个进程生成,2- 3个检查点的配额,因此max_wal_size=30GB(3 x 10GB)。
 

(4)checkpoint_completion_target

在CHECKPOINT期间,数据库需要执行以下三个基本步骤:
  • 识别共享缓冲区中的所有脏(修改)块
  • 将所有这些缓冲区写入磁盘(或更改为文件系统缓存)
  • fsync()所有修改的文件写入磁盘
  只有当所有这些步骤完成时,检查点才能被认为是完整的.尽可能快地执行这些步骤,即一次性写入所有脏缓冲区,然后在文件上调用fsync,实际上这是PostgreSQL 8.2开始使用的.但是由于大量写入时文件系统的高速缓存饱和,会影响用户会话,导致I/O停顿.为了解决这个问题,PostgreSQL 8.3引入了“扩展检查点”的概念,而不是一次写入所有的数据,写入时间很长,这给了操作系统时间来刷新后台的脏数据,从而使降低fsync()调用成本.
checkpoint_completion_target = 0.5这个配置参数说明所有的写入都要完成,到下一个检查点有多远.
checkpoint_completion_target = 0.5
  假设检查点仅通过checkpoint_timeout=5min触发,数据库将限制写入,以便最后一次写入在2.5分钟后完成.然后操作系统另外需要2.5分钟才能将数据刷新到磁盘,以便5分钟后调用fsync.
  留给系统的2.5分钟可能看起来很多,考虑到超时时间(checkpoint_timeout)只有30秒.您可以将checkpoint_completion_target例如增加到0.85,这将留给系统大约45秒,比它需要的30秒多一点。这不建议,因为在密集写入的情况下,检查点可能比max_wal_size更快地触发.然而,处理写入密集型工作负载的系统不太可能运行更高的checkpoint_timeouts值,默认的completion_target值显然太低.例如,超时设置为30分钟,它强制数据库在前15分钟(写入速率的两倍)中执行所有写入,然后在剩余的15分钟内空闲。
替代方案是可以尝试使用此公式大致设置checkpoint_completion_target
(checkpoint_timeout - 2min) / checkpoint_timeout
checkpoint_timeout=30分钟约为0.93.建议不要超过0.9
 

4.总结

  • 大多数检查点应该是基于时间的,即由checkpoint_timeout触发
  • 性能(不频繁检查点)与恢复所需时间(频繁检查点)之间的妥协
  • checkpoint_timeout值在15-30分钟之间是比例合适的,但到1小时不是什么坏事
  • 在决定checkpoint_timeout后,通过估计WAL的数量选择max_wal_size
  • 设置checkpoint_completion_target以便内核将数据刷新到磁盘的时间足够(但不是太多)
  • 调整内核参数vm.dirty_expire_centisecs  vm.dirty_background_bytes 以防止内核在页面缓存中累积大量脏数据

个人参数推荐配置

#不建议频繁做检查点,否则XLOG会产生很多的FULL PAGE WRITE
checkpoint_timeout = 30min
#根据自己的硬盘io设置,如果硬盘io比较好可以设置比较大,否则会带来性能上是负担(值建议为2的n次方),建议是SHARED BUFFER的2倍
max_wal_size = 16GB
#一般设置max_wal_size的1/4(值建议为2的n次方)
min_wal_size = 4GB
checkpoint_completion_target = 0.9
 

你可能感兴趣的:(PostgreSQL,数据库,postgresql,检查点)