PostgreSQL 检查点会发生什么?

Kon*_*rus 25 postgresql

这是我的检查点日志的一部分:

2014-03-26 11:51:29.341 CDT,,,18682,,532854fc.48fa,4985,,2014-03-18 09:15:24 CDT,,0,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,,,18682,,532854fc.48fa,4987,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 16774 buffers (1.6%); 0 transaction log file(s) added, 0 removed, 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,,,18682,,532854fc.48fa,4989,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 14436 buffers (1.4%); 0 transaction log file(s) added, 0 removed, 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,,,18682,,532854fc.48fa,4991,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 13277 buffers (1.3%); 0 transaction log file(s) added, 0 removed, 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,,,18682,,532854fc.48fa,4993,,2014-03-18 09:15:24 CDT,,0,LOG,00000,"checkpoint complete: wrote 20765 buffers (2.0%); 0 transaction log file(s) added, 0 removed, 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",,,,,,,,,""
Run Code Online (Sandbox Code Playgroud)

我注意到有时我们的数据库很慢——你可以看到大量通常较短的查询卡住了比现在更长的时间。它经常发生,没有明确的罪魁祸首。

问题:检查点会导致这个吗?检查点的“同步”阶段会发生什么?

Cra*_*ger 37

在其操作期间,PostgreSQL 记录对事务日志文件的更改,但它不会立即将它们刷新到实际的数据库表中。它通常只是将更改保留在内存中,并在请求时从内存中返回它们,除非 RAM 开始变满并且必须将它们写出。

这意味着如果它崩溃,磁盘上的表将不会是最新的。在开始备份之前,它必须重播事务日志,将更改应用于磁盘表。对于一个大而繁忙的数据库,这可能需要一段时间。

出于这个原因,并且为了事务日志不会永远保持增长,PostgreSQL 会定期执行检查点以确保数据库处于干净状态。它将所有挂起的更改刷新到磁盘并回收用于保留更改的崩溃恢复记录的事务日志。

这种刷新发生在两个阶段:

  • 缓冲write()的脏shared_buffers表;和
  • fsync() 受影响的文件,以确保更改确实命中磁盘

这两者都会增加磁盘 I/O 负载。这些写入引起的争用会减慢读取速度,也会减慢提交事务所需的 WAL 段的刷新。

这是一个长期存在的挑战,但随着我们看到具有越来越多 RAM 的系统,它们可以缓冲更多数据并花费更长的时间将其写出,因此情况变得更糟。正如这篇 LWN.net 文章中所讨论的,目前 Linux 和 PostgreSQL 社区之间正在讨论如何处理这个问题。(如果人们不订阅,LWN.net 将无法继续撰写此类出色的作品。我是订阅者并分享此链接,因为它有用且内容丰富。如果您想查看更多内容,请考虑订阅那类的东西。)

目前您可以做的减少检查点影响的主要事情是通过增加来分散检查点活动,checkpoint_completion_target以便在最终检查点到达时写出更多数据。但是,这有成本 - 如果您更新页面(例如)十次,它可能会在具有高完成目标的检查点之前多次写入磁盘,即使它只必须严格写出一次以确保崩溃安全。更高的完成目标使 I/O 模式更流畅,但总体 I/O 开销更大。

您可以做的另一件事是告诉您的操作系统在数据缓冲写入时立即开始写入数据。这就像设置的内核端,checkpoint_completion_target并且具有类似的权衡。见在Linux虚拟机的文件,特别是dirty_background_bytesdirty_background_ratiodirty_expire_centisecs