postgresql之checkpoint(检查点)

宇文飞翮
2023-12-01
检查点(Checkpoints)是事务序列中的点,我们保证在该点之前的所有日志信息都更新到数据文件中去了。在检查点时,所有脏数据页都冲刷到磁盘并且向日志文件中写入一条特殊的检查点记录。结果是,在发生崩溃的时候,恢复器就知道应该从日志中的哪个点(称做 redo 记录)开始做 REDO 操作,因为在该记录前的对数据文件的任何修改都已经在磁盘上了。在完成检查点处理之后,任何在redo记录之前写的日志段都不再需要,因此可以循环使用或者删除。(在进行 WAL 归档的时候,这些日志在循环利用或者删除之前必须先归档)。
    服务器的后端写进程将每隔这段时间就自动执行一个检查点。 每隔 checkpoint_segments 个日志段就创建一个检查点, 或者每隔 checkpoint_timeout 秒创建一个,以先到为准。缺省设置分别是 3 个段和 300 秒。 我们也可以用 SQL 命令 CHECKPOINT 强制一个检查点。
    减少 checkpoint_segments 和/或 checkpoint_timeout 会令检查点更频繁一些。 这样就允许更快的崩溃后恢复(因为需要重做的工作更少)。不过,我们必须在这个目的和更频繁地冲刷脏数据页所带来的额外开销之间取得平衡。 另外,为了保证数据页的一致性,在每个检查点之后的第一次数据页的变化会导致对整个页面内容的日志记录。 因此,检查点时间间隔短了会导致输出到 WAL 日志中的数据的增加,会抵销一部分缩短间隔的目标, 并且怎么着都会产生更多的磁盘 I/O。
    检查点开销相当高,首先是因为它需要写出所有当前脏的缓冲区,其实是因为他们导致上面讨论的额外的后继 WAL 流量。 因此把检查点参数设置得足够高,让检查点发生的频率降低是明智的。要对你的检查点参数的一个简单自检,可以设置 checkpoint_warning 参数。如果检查点发生的间隔接近 checkpoint_warning 秒, 那么将向服务器日志输出一条消息,建议你增加 checkpoint_segments 的数值。 偶尔出现的这样的警告并不会导致警告,但是如果它出现得太频繁,那么就应该增加检查点控制参数。
    在pg_xlog目录下至少会有一个 WAL 段文件,而且通常不会超过 2 * checkpoint_segments + 1 个文件。每个段文件通常 16MB 大(当然你可以在编译服务器的时候修改它)。你可以用这些信息来估计 WAL 需要的空间。 通常,如果一个旧的日志段文件不再需要了,那么它将得到循环使用(重命名为顺序的下一个可用段)。 如果由于短期的日志输出峰值,导致了超过 2 * checkpoint_segments + 1 个段文件, 那么到系统再次回到这个限制之内的时候,多于的段文件会被删除,而不是循环使用。
   在完成一个检查点并且日志文件冲刷了之后,检查点的位置保存在了文件 pg_control 里。因此在需要做恢复的时候, 后端首先读取 pg_control 和检查点记录; 然后它通过从检查点记录里标识的日志位置开始向前扫描执行 REDO 操作。 因为数据页的所有内容都保存在检查点之后的第一个页面修改的日志里, 所以自检查点以来的所有变化都将被恢复到一个一致的状态。
    但是为了处理 pg_control 可能的损坏, 我们实际上应该实现对现存的日志段的反向读取顺序 -- 从最新到最老 -- 这样才能找到最后的检查点。这些还没有实现。 pg_control 很小(比一个磁盘页小),因此它出现只写了一部分的问题的概率几乎为零, 到目前为止,我们还没有看到只是说不能读取 pg_control 自身的错误。 因此,尽管这在理论上是一个薄弱环节,但是 pg_control 看起来似乎并不是实际会发生的问题。 


http://publish.it168.com/2005/0919/20050919029201.shtml

 类似资料: