受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
开发版本: 19 / devel
此文档适用于不受支持的 PostgreSQL 版本。
您可能需要查看当前版本的相同页面,或上面列出的其他受支持版本。

28.2. 数据校验和 #

默认情况下,数据页受校验和保护,但也可以选择为集簇禁用。启用后,每个数据页 都包含一个校验和,在页面写入时更新,并在页面每次被读取时进行验证。只有数据 页受校验和保护;内部数据结构和临时文件不受保护。

可以在使用 initdb 初始化集簇时禁用校验和。之后也可以作为离线操作,或者在允许并发访问的运行中 集簇上在线启用或禁用。数据校验和是在整个集簇级别启用或禁用的,不能为单个 数据库、表或复制的集簇成员分别指定。

可以通过查看只读配置变量 data_checksums 的值来确认 集簇当前的校验和状态,执行命令 SHOW data_checksums 即可。

在尝试从页面损坏中恢复时,可能需要绕过校验和保护。为此,请临时设置配置参数 ignore_checksum_failure

28.2.1. 离线启用校验和 #

pg_checksums 程序可用于在离线集簇上启用或禁用数据校验和,也可以用来验证校验和。

28.2.2. 在线启用校验和 #

可以通过调用相应的 函数 在线启用 或禁用校验和。

启用和禁用数据校验和都分两个阶段完成,中间由一次检查点分隔,以确保持久性。 不同状态及其转换关系如 Figure 28.1 所示,本节 将进一步说明。

Figure 28.1. 数据校验和状态


启用校验和会把集簇校验和状态设为 inprogress-on。在此期间, 校验和会被写入,但不会被验证。除此之外,还会启动一个后台工作进程,用于为集簇 中所有现有数据启用校验和。该工作进程完成集簇中所有数据库的处理后,校验和状态 会自动切换为 on。该处理会占用两个后台工作进程,因此要 确保 max_worker_processes 至少还能容纳另外两个进程。

该过程在开始前会先等待所有打开的事务结束,以便确认不存在在尚未提交的事务内部 创建、从而对启用校验和的过程不可见的表。它还会在完成前,针对每个数据库等待所 有预先存在的临时表被移除。如果应用中使用了生命周期较长的临时表,则可能需要终 止这些应用连接,以便该过程完成。

如果集簇在 inprogress-on 状态下由于任何原因停止,或者处理 被中断,那么必须手工重新启动校验和启用过程。为此,在集簇重启后重新执行 pg_enable_data_checksums() 函数。该过程会从头开始,不支 持从中断处继续。若集簇在 inprogress-off 状态下停止,则在 集簇重启时,校验和状态会被设为 off

禁用数据校验和会把数据校验和状态设为 inprogress-off。 在此期间,校验和会被写入,但不会被验证。所有进程确认该变更后,状态会自动设为 off

在数据校验和正在被启用时禁用数据校验和,会中止当前处理。

28.2.2.1. 在线操作对系统的影响 #

启用数据校验和会给系统带来显著的 I/O 压力,因为所有数据库页面都需要重写, 并且既要写入数据文件,也要写入 WAL。可以通过 pg_enable_data_checksums() 函数的 cost_delaycost_limit 参数进行节流,从而限制影响。

  • I/O:所有页面都需要计算并写入数据校验和,这会生成大量脏页,之后这些脏页还 需要刷盘,同时也会写入 WAL。

  • 复制:当备库在 WAL 流中收到数据校验和状态变更时,它会发起一个 重启点,以便把 当前状态刷入 pg_control 文件。重启点会把当前状态刷到 磁盘,并在完成前阻塞重做。这反过来会引入复制延迟,在同步备库上还会阻塞 主库。在过程启动前减小 max_wal_size,有助于缩短 重启点完成所需的时间。

  • 关闭/重启:如果在启用数据校验和期间服务器被关闭或重启,处理过程不会恢复, 所有页面都需要重新计算并重写。应当在无需常规维护或处于服务窗口期间启用数据 校验和。

禁用数据校验和时不会产生 I/O,但仍然需要检查点。