PG启用checksum数据块校验及pg_checksums、pg_verify_checksums命令

0    1435    7

Tags:

👉 本文共约4759个字,系统预计阅读时间或需18分钟。

checksum简介

在计算机系统中,checksum 通常用于校验数据在传输或存取过程中是否发生错误。PostgreSQL从 9.3 开始支持 checksum,以发现数据因磁盘、 I/O 损坏等原因造成的数据异常。

PostgreSQL 从 9.3 开始支持数据页的 checksum,可以在执行 initdb 时指定 -k--data-checksums 参数开启 checksum,但开启 checksum 可能会对系统性能有一定影响,官网描述如下:

Use checksums on data pages to help detect corruption by the I/O system that would otherwise be silent. Enabling checksums may incur a noticeable performance penalty. If set, checksums are calculated for all objects, in all databases. All checksum failures will be reported in the pg_stat_database view.

视图pg_stat_database记录了校验和数据页失败的页数。

启用 checksum 后,系统会对每个数据页计算 checksum,从存储读取数据时如果检测 checksum 失败,则会发生错误并终止当前正在执行的事务,该功能使得 PostgreSQL 自身拥有了检测 I/O 或硬件错误的能力。

Checksum 引入一个 GUC 参数 ignore_checksum_failure,该参数若设置为 true,checksum 校验失败后不会产生错误,而是给客户端发送一个警告。当然,checksum 失败意味着磁盘上的数据已经损坏,忽略此类错误可能导致数据损坏扩散甚至导致系统奔溃,此时宜尽早修复,因此,若开启 checksum,该参数建议设置为 false,默认为false。

PostgreSQL checksum 行为:

1、开启checksum后,PostgreSQL 从shared buffer把数据write出去,需要计算checksum。

2、开启checksum后,从shared buffer外面(disk, os page cache)读取BLOCK到shared buffer里面,需要计算block的checksum,对比存储在page head里头的checksum是否一致。

3、已经在shared buffer里面的block,变更、读取时并不需要计算checksum。

数据页的 checksum 在从 Buffer pool 刷到存储时才设置,当页面再次读取至 Buffer pool 时进行检测。PostgreSQL 会在页面从存储读入内存时检测其是否可用,调用函数为 PageIsVerified,该函数不仅会检测正常初始化过的页(non-zero page),还会检测 全零页(all-zero page)

为什么会出现 全零页 呢?
在特定场景下表中可能出现 全零页,比如有进程扩展了一个表,即在该表中添加了一个新页,但在 WAL 日志写入存储之前,进程崩溃了。此时新加的页可能已经在表文件中,下次重启时就会读取到。

对于 non-zero page,检测其 checksum 是否一致以及 page header 信息是否正确,若 checksum 失败,但 header 信息正确,此时会根据 ignore_checksum_failure 值判断验证是否通过;对于 all-zero page,如果为全零,则验证通过。

若验证失败,两种处理方式:

  • 若读取数据的模式为 RBM_ZERO_ON_ERROR 且 GUC 参数 zero_damaged_pages 为 true,则将该页全部置 0

  • 报错,invalid page

Checksum 使 PostgreSQL 具备检测因硬件故障或传输导致数据不一致的能力,一旦发生异常,通常会报错并终止当前事务,用户可以尽早察觉数据异常并予以恢复。当然,开启 checksum 也会引入一些开销,体现在两个方面:

  • 计算数据页的 checksum 会引入一些 CPU 开销,具体开销取决于 checksum 算法的效率
  • checkpoint 后,若因更新 Hint Bits 将页面第一次置为 dirty 会写一条记录 Full Page Image 的 WAL 日志,以用于恢复因更新 Hint Bits 产生的破碎页。

对于数据可用性要求较高的场景,通常建议将 full_page_writes 和 checksum 都打开,前者用于避免写失败导致的数据缺失,后者用于尽早发现因硬件或传输导致数据不一致的场景,一旦发现,可以利用 full_page_writes 和 checksum 记录在 WAL 日志中的 Full Page Image 进行数据恢复。

查看 checksum

PostgreSQL 10 在 pageinspect 插件中添加了函数 page_checksum() 用来查看 page 的 checksum,当然使用 page_header() 也可以查看 page 的 checksum,如下:

PG12命令之pg_checksums

简介

官网:http://postgres.cn/docs/13/app-pgchecksums.html

对于一些数据可靠性要求很高的场景,例如金融领域,建议打开数据块的checksum校验功能。

在PG 12之前,需要在用initdb命令创建数据库的时候加上-k参数来启用checksum功能;从PG12开始,提供了pg_checksums命令,可以把一个没有checksum功能的数据库转换为具有该功能的数据库。

pg_checksums 的作用是在PostgreSQL数据库集簇中启用、禁用或检查数据校验和。

pg_checksums在PostgreSQL集簇中检查、启用或禁用数据校验和。运行pg_checksums之前,必须彻底关闭服务器。验证校验和时,如果没有校验和错误,则退出状态为零,如果检测到至少一个校验和失败,则退出状态为非零。启用或禁用校验和时,如果操作失败,则退出状态为非零。

验证校验和时,集簇中的每个文件都要被扫描。启用校验和时,集簇中的每个文件都会被原地重写。禁用校验和时,仅更新pg_control文件。

pg_checksums命令是对pg11的pg_verify_checksums命令的改进,即在PG12中,将命令行工具pg_verify_checksums改名为pg_checksums。

语法

下列命令选项可用:

标签:

Avatar photo

小麦苗

学习或考证,均可联系麦老师,请加微信db_bao或QQ646634621

您可能还喜欢...

发表回复