2014-03-26 11:51:29.341 CDT,18682,532854fc.48fa,4985,2014-03-18 09:15:24 CDT,LOG,00000,"checkpoint complete: wrote 15047 buffers (1.4%); 0 transaction log file(s) added,0 removed,30 recycled; write=68.980 s,sync=1.542 s,total=70.548 s; sync files=925,longest=0.216 s,average=0.001 s","" 2014-03-26 11:56:05.430 CDT,4987,"checkpoint complete: wrote 16774 buffers (1.6%); 0 transaction log file(s) added,31 recycled; write=72.542 s,sync=17.164 s,total=89.733 s; sync files=885,longest=3.812 s,average=0.019 s","" 2014-03-26 12:01:21.650 CDT,4989,"checkpoint complete: wrote 14436 buffers (1.4%); 0 transaction log file(s) added,33 recycled; write=122.350 s,sync=5.212 s,total=127.676 s; sync files=924,longest=3.740 s,average=0.005 s","" 2014-03-26 12:06:25.028 CDT,4991,"checkpoint complete: wrote 13277 buffers (1.3%); 0 transaction log file(s) added,29 recycled; write=126.217 s,sync=5.733 s,total=131.991 s; sync files=894,longest=1.859 s,average=0.006 s","" 2014-03-26 12:10:41.958 CDT,4993,"checkpoint complete: wrote 20765 buffers (2.0%); 0 transaction log file(s) added,28 recycled; write=88.015 s,sync=10.818 s,total=98.872 s; sync files=881,longest=2.690 s,average=0.012 s",""
我注意到有时候我们的数据库很慢 – 你可以看到大量通常很短的查询比现在停留的时间长得多.它经常发生,没有明确的罪魁祸首.
问题:检查点可能导致此问题吗?在检查点的“同步”阶段会发生什么?
这意味着如果它崩溃,磁盘表将不是最新的.它必须重播事务日志,将更改应用于磁盘表,然后才能开始备份.这对繁忙的大型数据库来说可能需要一段时间.
由于这个原因,并且事务日志不会永远增长,Postgresql会定期执行检查点,以确保数据库处于干净状态.它将所有挂起的更改刷新到磁盘,并回收用于保留更改的崩溃恢复记录的事务日志.
这种冲洗分两个阶段进行:
>对表中的脏shared_buffers缓冲write();和
> fsync()受影响的文件,以确保更改真正击中磁盘
这两者都可以增加磁盘I / O负载.这些写入引起的争用可能会降低读取速度,并且还会减慢为提交事务所需的WAL段的刷新速度.
这是一个长期存在的挑战,但随着我们看到拥有越来越多内存的系统,它们会越来越糟,因此它们可以缓冲更多数据并花费更长时间来写出来. There’s discussion between the Linux and PostgreSQL communities on how to deal with this at the moment,as discussed in this LWN.net article.(如果人们不订阅,LWN.net将无法继续撰写这类伟大的作品.我是订阅者并分享此链接,因为它有用且内容丰富.请考虑订阅,如果你想看到更多这种事情.)
您目前可以采取的主要措施是减少检查点的影响,方法是通过增加checkpoint_completion_target来扩展检查点活动,以便在最终检查点到达时写出更多数据.但这有一个成本 – 如果你更新一个页面(比方说)十次,它可能会在具有高完成目标的检查点之前多次写入磁盘,即使它只是为了确保崩溃安全而只需要写出一次.更高的完成目标使I / O模式更平滑,但总体I / O开销更高.
您可以做的另一件事就是告诉您的操作系统在获得缓冲写入时立即开始写入数据.这就像设置checkpoint_completion_target的内核一样,并且有类似的权衡.请参见the linux vm documentation,特别是dirty_background_bytes,dirty_background_ratio,dirty_expire_centisecs.