PostgreSQL检查点会发生什么?


22

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

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",,,,,,,,,""

我注意到有时我们的数据库速度很慢-您会看到大量通常很短的查询比现在滞留的时间更长。它定期发生,没有罪魁祸首。

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

Answers:


32

在运行过程中,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


这篇文章散布了很长时间,我认为这不会引起问题。同步又如何呢?
Konrad Garus 2014年

@KonradGarus同步不应该是一种世界末日的操作,但是无论如何它通常都是这样。阅读我上面链接的文章,尽管从相当技术角度来看,它是问题的非常及时且有用的摘要。简短的版本是“ Linux上的fsync()倾向于完全破坏与fsync()并发的任何I / O的性能”。您可以使用上面列出的调整选项来减轻这种情况,以减少必须由fsync清除的数量。
Craig Ringer 2014年

1

冲洗造成超过脏OS文件系统缓存dirty_bytes或者dirty_ratio 前景阻塞操作!

内核可调参数dirty_bytesdirty_background_bytesdirty_ratiodirty_background_ratiodirty_centisecs控制脏OS文件系统缓冲区刷新到磁盘。 dirty_bytes是阈值(以字节dirty_ratio为单位),是阈值(占总内存的比率)。 dirty_background_bytesdirty_background_ratio阈值相似,但是刷新在后台发生,并且在完成之前不会阻止其他读/写操作。 dirty_centisecs开始刷新之前可以经过的毫秒数。

最近,随着现代计算机的内存容量急剧增加,这些可调参数的默认值在Linux中降低了。的5和10%,甚至比dirty_background_ratiodirty_ratio256GB的机器上可淹没的I / O系统。

调优dirty_background_bytesdirty_background_ratio开始在后台刷新脏缓冲区很棘手。幸运的是,您可以通过将新值回显到适当的文件来调整这些设置,而不必停止PostgreSQL或主机。

$ sudo echo [int value of bytes] > /proc/sys/vm/dirty_background_bytes

例如,设置脏字节数以触发后台刷新。如果您使用的是电池后备,电容器后备或闪存RAID卡(您确实想在发生崩溃的情况下保留数据,不是吗?)首先要调整dirty_background_bytes为写入缓存缓冲区大小的1/2并dirty_bytes缩小到该尺寸的3/4 使用iostat监视您的I / O配置文件,如果仍然看到延迟问题,这意味着您的数据库写负载仍然压倒了文件缓冲区高速缓存刷新。调低这些值,直到延迟改善或考虑升级您的I / O子系统。FusionIO卡和SSD是实现极高I / O吞吐量的两种可能性。

祝好运!


您对“脏”数据的评论与缓慢有关。本质上:脏率越大,在刷新开始之前为脏数据分配的缓冲区就越多。因此,最小化刷新延迟意味着增加脏缓冲区或增加脏数据可以保留在内存中的时间。
Peter Teoh
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.