从pg_stat_bgwriter中能看到些什么?

从pg_stat_bgwriter中能看到些什么?

今天老白和大家探讨一下如何通过这个视图来分析一些和PG数据库缓冲区刷新性能的方法。首先我们来看这个性能视图中的字段。我们以一个实际的例子来看。

从pg_stat_bgwriter中能看到些什么?

  • checkpoints_timed:计划检查点的发生次数,这种检查点是checkpoint_timeout参数规定的超时达到后系统启动的checkpoint;

  • checkpoints_req:非计划检查点的次数。有些朋友把这个指标定义为手工检查点的次数,实际上这是不准确的。手工检查点是因为执行某些命令触发的检查点,这个指标包含这类检查点,除此之外,还有一类xlog checkpoint检查点也属于这类检查点。xlog ckpt是指当某些数据库预定的阈值达到时启动的检查点,比如WAL已经超出了max_wal_size或者checkpoint_segments,也会触发xlog ckpt;

  • checkpoint_write_time:ckpt写入的总时长;

  • checkpoint_sync_time:ckpt同步文件的总时长;

  • buffers_checkpoint:由checkpointer清理的脏块;

  • buffers_clean:由bgwriter清理的脏块数量;

  • buffers_backend:由backend清理的脏块数量;

  • maxwritten_clean:bgwriter清理脏块的时候达到bgwriter_lru_maxpages后终止写入批处理的次数,为了防止一次批量写入太大影响数据块IO性能,bgwriter每次都有写入的限制。不过这个参数的缺省值100太小,对于负载较高的数据库,需要加大;

  • buffers_backend_fsync:backend被迫自己调用fsync来同步数据的计数,如果这个计数器不为零,说明当时的fsync队列已经满了,存储子系统肯定出现了性能问题;

  • stats_reset:上一次RESET这些统计值的时间。

了解了上面的一些计数器的基本情况,下面我们就可以用这些计数器进行分析了。

首先是计划检查点的比例,如果PG数据库的所有检查点都是按照checkpoint_timeout参数的计划进行的,那么说明系统的脏数据产生量对系统影响不大,不过事实上很难做到这一点,因为有时候WAL产生的比较快,那么在计划检查点启动前,有可能PG需要强制进行一次xlog checkpoint了。我们看上面例子里的第三组数据,计划检查点还没执行,就已经多了100多次xlog checkpoint了,这是因为这个数据库在做一次比较大的数据更新。一般来说,让计划检查点比例保持在90%以上是我们的目标,当然不同的数据库系统的负载不同,这个目标也会有一定的调整。如果和CKPT相关的一些参数配置的不合理,或者shared buffer配置的不合理,也会导致计划检查点的比例偏低。

另外一组需要关注的数据是脏块是被谁刷回存储系统的。Oracle dba刚刚接触PG的时候很容易产生误解,因为PG的bgwriter、checkpointer和backend都可能把脏数据回写到存储上。正常情况下,我们希望大部分的脏数据都是bgwriter写回存储的,少量的脏数据是checkpointer写入的,更少的数据是backend写入的。因为backend写入数据是十分高成本的。不过好像事实上并非如此,backend写入的比例很高。

上面的这组数据十分的怪异,居然系统中86%的脏数据是backend写出的。backend申请shared buffer的时候找到了Lru链上的脏块,首先把脏块写回,再清理掉脏块,存入新的数据。这个操作本身就是高开销的,Oracle为了避免类似问题发生,采用了一种不同的扫描方法,当Oracle的server进程发现找到了一个脏块的时候,直接把这个块从lru链上摘下,链入lru-w链,等待dbwr处理,然后继续扫描,如果连续扫描到多个脏块和热块,无法获得可用的buffer的时候,就会产生一个free buffer wait事件。这种算法也是为了尽可能避免这种高开销的操作。PG的backend还做这种脏活,确实也是整体算法上的无奈。不过对于DBA来说,应该尽可能地通过调整降低backend回写脏块的数量。我们需要分析一下产生这种情况的原因。因为老白的这个系统中的shared_buffers只有1GB,而系统负载相对较大。我们再来看一个有8GB shared_buffers的系统,通过benchmark压测一段时间后的结果:

大概74%的脏块是ckpt写入的,backend写入的比例大约是21%,在非压测的时段,backend回写脏块的比例大约是18%左右。这个数据库的shared buffers仍然是偏低的,进一步加大后还可以进一步降低backend回写脏块的比例。这是因为如果shared buffer上设置偏低,会导致缓冲块还没等到bgwriter和checkpointer回写,就被backend找到并要进行重用那个了。这个系统的bgwriter写入的脏块的比例过低,只有5%。按照正常的情况,bgwriter应该是脏块回写的主力,checkpointer写入的脏块量远大于bgwriter。bgwriter的表现很懒惰,是什么原因呢?PG的初始化参数往往都是偏低的,并不适合我们的数据库应用。比如bgwriter相关的几个参数

  • bgwriter_delay:bgwriter两个任务之间的休眠时间的初始值为200毫秒;

  • bgwriter_lru_maxpages:每次bgwriter任务写buffer的最大page数,一旦达到这个数量,bgwriter就结束任务开始休息,也就是说bgwriter休眠200毫秒,然后写入几十毫秒就又开始了休息,这比欧洲人民的工作时间都短得多,怪不得干不了多少活呢;

  • bgwriter_lru_multiplier:这个参数用于评估下一次写任务的数量,其依据是这段时间内新申请的buffer数量的倍数,如果这个参数乘以新增加buffer分配的数量后小于bgwriter_lru_maxpages,那么有可能下一个写任务的数量会小于预期的写入量。将这个参数调大,会增加bgwriter回写脏块的数量,不过会增加写IO压力,将这个参数调小,可以降低写IO压力,不过可能导致backend写脏块的比例增加。不同负载的系统中,这个参数的值应该是需要做调整的,而不是只是用缺省值2。如果你发现你的系统的写IO压力还不大,但是 bgwriter写比例偏低,backend写比例偏高,那么尝试加大这个参数还是有效的。

老白在上面的那个系统中,把bgwriter_delay调整到最低(10),bgwrite_lru_maxpages调整到3000,bgwriter_lru_multiplier调整为0,然后再跑一下压测,看到的三种脏块回写的比例有了明显的变化。

同时整个数据库的TPMC也从63万提高到70万,居然提升了10%。看样子PG数据库的参数,不认真调整调整,整体性能还是发挥不出来啊。

PG的动态性能视图并没有Oracle那么丰富,不过实际上如果认真去看,还是能看到很多十分有价值的信息的。从pg_stat_bgwriter这一行数据里我们居然能看出这么多门道来,是不是感觉有点意外。学习PG数据库,只要认真的去研究,你会有更多的发现。

从pg_stat_bgwriter中能看到些什么?》来自互联网,仅为收藏学习,如侵权请联系删除。本文URL:http://www.bookhoes.com/399.html