PostgreSQL Field Guide

在线启停 data checksums

PostgreSQL 19 支持在运行中的集群上在线启用/禁用 data checksums——操作步骤、I/O 代价、节流与进度观测

PostgreSQL 19 仍处于 Beta

截至 2026-08,PostgreSQL 19 尚未正式发布。下文函数签名、状态与视图列以 PostgreSQL 19 文档为准;用于生产前请对照正式 release notes 复核。

Data checksums 在每个数据页里存一个校验值,页面写出时计算、读入时验证,是发现存储和文件系统损坏的主要手段。从 PostgreSQL 18 起 initdb 默认为新集群开启。但在更老 major 版本上初始化的集群往往至今没开——这正是本页要解决的场景。

PostgreSQL 18 及之前:pg_checksums 必须停机

到 PostgreSQL 18 为止,改变既有集群的 checksum 状态只能用 pg_checksums,而它要求服务器干净关闭。启用 checksum 需要原地重写所有关系块,TB 级集群的维护窗口以小时计,且操作中途严禁启动集群。对要求始终在线的系统,"补开 checksum" 几乎排不进日程。

在线启用

PostgreSQL 19 新增了 SQL 函数,在集群正常运行、客户端照常访问的情况下切换 checksum,见官方文档 28.2 节 Data Checksums

-- 查看当前状态:off / inprogress-on / on / inprogress-off
SHOW data_checksums;

-- 开始启用;cost_delay / cost_limit 用于节流
SELECT pg_enable_data_checksums(cost_delay => 10, cost_limit => 1000);

调用之后发生什么:

  1. 集群状态变为 inprogress-on。此后页面写出时计算 checksum,但读入时暂不验证
  2. 一个 launcher 为每个 database 启动后台 worker,遍历所有关系、把每个页标记为脏,使其带 checksum 重写。
  3. 所有 database 处理完毕后,状态自动切换为 on,读时验证开始。

需要知道的前提与卡点:

  • 该过程占用两个后台 worker 槽位——确认 max_worker_processes 有余量。
  • 开始前要等待所有已打开的事务结束;对每个 database,还要等启用那一刻之前存在的临时表全部被删除。使用长生命周期临时表的应用可能无限期卡住流程,必要时需要终止对应连接。
  • 如果集群在 inprogress-on 期间停止,不会断点续做:重启后重新执行 pg_enable_data_checksums(),重写从头开始。安排在没有重启、没有 failover 的窗口。

I/O 代价与进度观测

启用 checksum 要重写集群里的每一个页——脏页刷盘加上重写产生的 WAL,I/O 冲击是实打实的。pg_enable_data_checksums()cost_delay / cost_limit 参数沿用 vacuum 那套基于成本的节流模型;生产环境建议从保守值起步,同时观察延迟。

进度通过 pg_stat_progress_data_checksums 观测:launcher 一行(跟踪 databases_total / databases_done),每个 worker 一行(跟踪 relations_total / relations_done 以及当前关系的 blocks_total / blocks_done):

SELECT pid, datname, phase,
       databases_total, databases_done,
       relations_total, relations_done,
       blocks_total, blocks_done
FROM pg_stat_progress_data_checksums;

phase 列区分 enablingdisablingwaiting on barrier(等待各后端确认状态变更)和 waiting on temporary tables——后两个解释了大多数"看似卡住"的情况。这些进程也会出现在 pg_stat_activity 里,backend_typedatachecksums launcher / datachecksums worker

文档中关于复制的一个提醒:standby 从 WAL 流中收到 checksum 状态变更时会强制做一次 restartpoint,完成前阻塞 redo,可能造成复制延迟——同步 standby 上还会反过来阻塞 primary。开始前调低 max_wal_size 可以缩短这次 restartpoint。

在线禁用

SELECT pg_disable_data_checksums();

状态先变为 inprogress-off(仍写 checksum、不再验证),所有后端确认后落定到 off。禁用不重写任何页面,没有 I/O 冲击,但仍需 checkpoint。在启用过程中执行禁用会中止启用。如果集群在 inprogress-off 期间停止,重启后状态即为 off

硬件加速的校验和计算

数据页里存的校验和用的是 PostgreSQL 自有的、基于 FNV-1a 的算法,而不是 CRC;x86-64 上会在运行时自动选用 AVX2 向量化实现。CRC-32C 保护的是 WAL 记录:运行时在 x86 上自动分发到 SSE4.2 或 AVX-512 指令,在 ARMv8 上使用 CRC32/PMULL 扩展(实现背景见 digoal 的 commit 解读;WAL 使用 CRC-32C 见官方文档 28.1 节 Reliability)。现代 CPU 上,日常保持 checksum 开启的 CPU 开销很小;主要成本是启用时的一次性重写,而不是常态运行。

与备份校验的联动

Checksum 与备份工具链在两个不同层面配合:

  • pg_basebackup 读取集群时默认逐页验证 checksum(除非指定 --no-verify-checksums);校验失败会以非零状态退出,并计入 pg_stat_database.checksum_failures。开了 checksum,每次基础备份就顺带完成一次全库损坏扫描。
  • pg_verifybackup 依据 backup_manifest 里的文件级哈希校验已完成的备份。它抓的是备份存储、传输过程中引入的损坏——与守护在线集群的页 checksum 是不同的失效域。

两者都应纳入 备份、恢复与 PITR 中的验证流程;checksum_failures 应接入 监控与日志 里的看板。

什么时候值得开

  • 在 PostgreSQL 18 修改默认值之前初始化、一直没开 checksum 的集群——现在没有停机这个借口了。
  • 有合规或完整性要求,必须能发现静默存储损坏的系统。
  • 希望 pg_basebackup 的内建验证兼作定期损坏巡检的系统。

可以暂缓的理由很窄:即用即弃的集群,或者存储栈已端到端校验(如 ZFS)且风险偏好较高的情况。注意只有 PostgreSQL 层的 checksum 才会被 PostgreSQL 自己的工具验证。PostgreSQL 19 的更多变化见版本总览

AI 提示词:规划 checksum 启用

规划一次在线 checksum 启用
帮我规划在生产 PostgreSQL 19 集群上在线启用 data checksums。

1. 集群情况:(填写——数据量、database 数量、max_worker_processes、是否有同步 standby、典型写入吞吐)
2. 请:
 - 给出确切命令:SHOW data_checksums,以及针对我的规模给出 pg_enable_data_checksums 的 cost_delay/cost_limit 起始值
 - 列出可能卡住流程的因素(长事务、长生命周期临时表)及各自的排查 SQL
 - 写出 pg_stat_progress_data_checksums 监控查询,并解释 launcher 行与 worker 行的区别
 - 说明 standby restartpoint 延迟风险,以及是否应先调低 max_wal_size
 - 给出中止/回退路径,包括中途重启集群的后果(inprogress-on 不续做)
3. 最后给出验证清单:最终 SHOW data_checksums、pg_stat_database.checksum_failures 基线、一次 pg_basebackup 试跑。

Last updated on

On this page