说说pg中的检查点(checkpoint)之一

       最近一直在使用pgbench对pg进行压测,在压测的过程中,发现checkpoint的发生会对数据库的性能产生极大的影响.

       想看到最近有没有发生checkpoint,有两种比较简单的方式:

        一个是不停的刷新pg_stat_bgwriter这个视图,这个视图中两个字段checkpoints_timed和checkpoints_req直接反映了PG已经发生或是正在发生的checkpoint次数,如果这两个字段的值发生了变化,就说明发生了checkpoint。如果凑巧正在做checkpoint,可以查询这个视图的另外的一个字段buffers_checkpoint,这个字段表明了checkpoint进程刷回了多少个脏的block回磁盘,在做checkpoint的过程中这个字段的结果将会不断累积。在PG的checkpoint进程内部的实现中,如果要做checkpoint,会首先将checkpoints_timed或是checkpoints_req字段关联的统计值加一,然后再来把脏块挨个写回(write)磁盘,每写一个就把相关的统计值加1。一般来说,如果checkpoint_segments设置得足够大(例如128个)并且脏数据块很多,那么在一次做checkpoint的过程可以持续100多秒都是可能的,因此是可以看到buffers_checkpoint这个字段在不断增加的。

       另外一个就是在postgresql.conf中打开log_checkpoints配置项,然后查看日志文件。在checkpoint开始时,会在日志文件中打印一行说checkpoint开始了,然后结束之后也会将本次checkpoint的统计信息打印出来,例如:

LOG:  checkpoint starting: time
LOG:  checkpoint complete: wrote 0 buffers (0.0%); 0 transaction log file(s) added, 0 removed, 0 recycled; write=0.002 s, sync=0.000 s
, total=0.011 s; sync files=0, longest=0.000 s, average=0.000 s

 注意这段日志里面第一行提到了是因为到点了(time)才做的checkpoint。

        前面提到的pg_stat_bgwriter视图中两个字段checkpoints_timed和checkpoints_req,在官方的英文文档中说得有些过于简洁,而被翻译成中文之后,结果有些晦涩。对于checkpoints_timed的解释,中文翻译过来是定期执行的检查点数这个基本上是对的,而对于checkpoints_req,英文文档是:Number of requested checkpoints that have been performed。应该是执行被请求的检查点数。至于被谁、在什么情况下请求的?都没有说明。

      对于checkpoints_timed统计的检查点,很容易理解,就是在过了checkpoint_timeout这个配置项指定的时间之后执行的检查点,这个实际上是checkpoint进程主动发起的检查点。他在日志中输出就是上面日志的内容。

      而对于checkpoints_req统计的检查点,实际上可以分为三种:一种是写的WAL距离上次的checkpoint位置已经超过了checkpoint_segments个WAL,那么这个时候需要做一个检查点了;另外一种就是做了比较重量的DML,例如创建了一个database,或是删除了一个database,或是修改了tablespace;最后一种就是用户直接通过SQL执行checkpoint这个命令而触发的检查点。

      checkpoints_req统计的检查点实际上就是checkpoint进程被动执行的。如何来触发checkpoint进程来执行这些检查点呢?很简单:我们知道PG是个多进程的程序,checkpoint的进程信息(包括进程ID)存在了共享内存的hash表中的,是通过名字可以查到的,那么可以获得checkpoint进程的ID、直接通过kill调用来发生某个特定的信号来告诉checkpoint进程需要执行检查点了。实际上也是这样实现的,大家可以看具体的源码。

     那么有个问题:如果过了checkpoint_timeout并且也接到了其他进程做checkpoint的请求了,那么该把谁加一呢?实际代码中是把checkpoints_req加一的。

      另外:PG中发生的checkpoint是否都会被checkpoints_timed和checkpoints_req统计呢?答案是否定的:在PG启动的过程中,postmaster做完了恢复会做一个checkpoint,这个时候还没有其他进程,参见StartupXLOG函数;另外,当PG退出时,checkpoint进程会做一个检查点,这个检查点也是不被统计的。但是,如果打开了log_checkpoints配置项,这两种情况都是会被记录下来的。

猜你喜欢

转载自scarbrofair.iteye.com/blog/2248930