在线启停 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);调用之后发生什么:
- 集群状态变为
inprogress-on。此后页面写出时计算 checksum,但读入时暂不验证。 - 一个 launcher 为每个 database 启动后台 worker,遍历所有关系、把每个页标记为脏,使其带 checksum 重写。
- 所有 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 列区分 enabling、disabling、waiting on barrier(等待各后端确认状态变更)和 waiting on temporary tables——后两个解释了大多数"看似卡住"的情况。这些进程也会出现在 pg_stat_activity 里,backend_type 为 datachecksums 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 启用
帮我规划在生产 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