PG 13新特性之pg_verifybackup
Tags: PGpg_verifybackup备份恢复备份校验新特性
简介
PG13版本引入两个特性来增强备份的验证:backup manifests (备份清单)和 pg_verifybackup
- backup manifests:使用 pg_basebackup 列出物理备份获取的内容
- pg_verifybackup:根据备份清单检查备份的完整性,流式基础备份的进度以及ANALYZE命令的进度。
一、backup manifests (备份清单)
备份清单是在使用pg_basebackup
创建完整物理备份时创建的
1、pg_basebackup
pg_basebackup - 物理备份的工具
backup manifest 相关选项:
1 2 3 4 5 6 7 8 | --manifest-checksums=algorithm 指定应应用于备份清单中包含的每个文件的校验和算法。目前,可用的算法有NONE、CRC32C、SHA224、SHA256、 SHA384和SHA512。默认值为CRC32C。 --manifest-force-encode 强制备份清单中的所有文件名采用十六进制编码。如果未指定此选项,则仅对非UTF8文件名进行十六进制编码 --no-manifest 禁用备份清单的生成。如果未指定此选项,则服务器将生成并发送备份清单,可以使用pg_verifybackup进行验证。清单是备份中存在的每个文件的列表,可能包含的所有WAL文件除外。它还存储大小、上次修改时间和每个文件的可选校验和。 |
2、内容
备份完成后在目标目录下会存在backup_manifest
文件,一个JSON格式的对象:
PostgreSQL-Backup-Manifest-Version
: 清单的版本Files
: 备份中包含的文件列表,以及每个文件的相对路径,来自 PGDATA 和重要的元数据,例如大小、最后修改时间和校验和WAL-Ranges
: 时间线、备份开始的LSN、备份结束的LSN等信息Manifest-Checksum
: 清单文件的校验和
1 2 3 4 5 6 7 8 9 10 | { "PostgreSQL-Backup-Manifest-Version": 1, "Files": [ { "Path": "backup_label", "Size": 226, "Last-Modified": "2022-06-06 03:13:02 GMT", "Checksum-Algorithm": "CRC32C", "Checksum": "9c1588c0" }, { "Path": "global/1262", "Size": 8192, "Last-Modified": "2022-06-02 09:47:56 GMT", "Checksum-Algorithm": "CRC32C", "Checksum": "a806d90f" }, …… ], "WAL-Ranges": [ { "Timeline": 1, "Start-LSN": "0/6F000028", "End-LSN": "0/6F000138" } ], "Manifest-Checksum": "6241b42fdc594dbf23c48390b9e204b6599d4cb6cef420efc374034e4d5a972b"} |
二、pg_verifybackup
pg_verifybackup - 验证备份完整性的工具
根据pg_basebackup进行备份时生成的backup_manifest
进行检查。
- plain 格式
- tar 格式:解压后才能进行验证
常用选项:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | -e --exit-on-error 检测到备份问题后立即退出。 如果没有指定这个选项,pg_verifybackup 将在检测到问题后继续检查备份,并将检测到的所有问题报告为错误。 -i path --ignore=path 在将备份中实际存在的数据文件列表与 backup_manifest 文件中列出的数据文件列表进行比较时,忽略指定的文件或目录,该文件或目录应表示为相对路径名。 -m path --manifest-path=path 使用指定路径的清单文件,而不是位于备份目录根目录中的清单文件。 -n --no-parse-wal 不要试图解析从该备份恢复所需的预写式日志数据。 -q --quiet 成功验证备份后不要打印任何内容。 -s --skip-checksums 不要验证数据文件校验和。但仍检查是否存在文件以及这些文件的大小。这样将会快得多,因为文件本身不需要读取。 -w path --wal-directory=path 尝试解析存储在指定目录中的 WAL 文件,而不是 pg_wal。 如果备份存储在与WAL存档不同的位置,则这可能很有用。 |
三、测试用例
情况一:不备份wal、plain
1)备份
1 2 3 4 5 6 7 8 9 10 11 | -- backup_manifest { "PostgreSQL-Backup-Manifest-Version": 1, "Files": [ { "Path": "backup_label", "Size": 226, "Last-Modified": "2022-06-06 03:13:02 GMT", "Checksum-Algorithm": "CRC32C", "Checksum": "9c1588c0" }, { "Path": "global/1262", "Size": 8192, "Last-Modified": "2022-06-02 09:47:56 GMT", "Checksum-Algorithm": "CRC32C", "Checksum": "a806d90f" }, …… ], "WAL-Ranges": [ { "Timeline": 1, "Start-LSN": "0/6F000028", "End-LSN": "0/6F000138" } ], "Manifest-Checksum": "6241b42fdc594dbf23c48390b9e204b6599d4cb6cef420efc374034e4d5a972b"} |
2)验证
1 2 3 4 5 6 7 | [postgres@node1 ~]$ /opt/pg13/bin/pg_verifybackup /backup/basebackup/test01/ pg_waldump: fatal: could not find any WAL file pg_verifybackup: error: WAL parsing failed for timeline 1 -- 加上 -n 选项 [postgres@node1 ~]$ /opt/pg13/bin/pg_verifybackup -n /backup/basebackup/test01/ backup successfully verified |
情况二:wal、plain
1)备份
2)验证
1 2 | [postgres@node1 ~]$ /opt/pg13/bin/pg_verifybackup /backup/basebackup/test02 backup successfully verified |
情况三:wal、tar
1)备份
四、原理
src/bin/pg_verifybackup/pg_verifybackup.c
pg_verifybackup 检查备份完整的步骤:
1、检查备份目录
- 忽略
backup_manifest
文件 - 忽略
pg_wal
目录,通过单独的机制验证 - 忽略
postgresql.auto.conf, recovery.signal, 和standby.signal
文件,这些文件可能会在pg_basebackup时创建会更改
2、查找并读取backup_manifest
文件
解析backup_manifest
文件时遇到的任何错误都视为FATAL
默认情况下在备份目录中查找,使用-m, --manifest-path=PATH
可以指定清单的位置
parse_manifest_file() - 解析清单文件,创建一个hash树 --> json_parse_manifest() - 解析JSON格式的清单文件 —>
-->1)pg_parse_json() - 实际的JSON解析器
-->2)verify_manifest_checksum() - 验证清单文件的校验和。清单文件的最后一行被排除在清单校验和之外,因为最后一行应该包含覆盖文件其余部分的校验和。
3、扫描备份目录的文件
将backup_manifest
上的记录的文件和磁盘上的文件进行比较,如果存在且size
也匹配的话,则会在清单的相应文件条目设置matched
标志。
没有设置标志的则是manifest
上提单的但是备份目录中不存在的
verify_backup_directory - 扫描备份目录,遍历备份目录下每一个文件
-->1)verify_backup_file() - 是目录:递归调用verify_backup_directory();
-->2)manifest_files_lookup() - 检查清单哈希中是否有条目,为NULL,则报错提示“XXX is present on disk but not in the manifest”
-->3)检查 size 是否匹配
report_extra_backup_files() - 扫描哈希表中未设置“匹配”标志的条目,报错提示“XXX is present in the manifest but not on disk”
4、验证文件的 checksum
这个步骤需要花费较大的代价
1 | -s, --skip-checksums |
verify_file_checksum - 验证单个文件的校验和
-->1)初始化校验和
-->2)逐块读取文件,同时更新校验和
5、使用清单来验证恢复备份所需的 WAL 日志记录是否存在,并且它们可以被读取和解析
1 | -n, --no-parse-wal |
默认情况下在备份目录的pg_wal
目录下查找,可以通过-w, --wal-directory=PATH
指定
backup_manifest
包含有关需要哪些预写式日志记录的信息,并且 pg_verifybackup
将使用该信息来调用 pg_waldump
来解析这些预写式日志记录
parse_required_wal - 解析WAL,调用 pg_waldump,根据timeline、StartLSN 和EndLSN
1 pg_waldump --quiet --path=\"%s\" --timeline=%u --start=%X/%X --end=%X/%X
6、验证结束
验证成功返回:backup successfully verified
,可以添加-q, --quiet
选项来决定验证成功不返回任何消息
pg_verifybackup命令详解
pg_verifybackup — 验证PostgreSQL集群的基础备份的完整性
大纲
pg_verifybackup
[option
...]
简介
pg_verifybackup用于根据备份时服务器生成的backup_manifest
检查使用pg_basebackup
进行的数据库群集备份的完整性。备份必须以“普通”格式存储;“tar”格式的备份可以在解压缩后进行检查。
需要注意的是,由pg_verifybackup执行的验证不包括也不可能包括运行中的服务器在尝试使用备份时执行的所有检查。 即使使用此工具,也应执行测试还原,并验证生成的数据库是否按预期工作,以及它们是否包含正确的数据。但是,pg_verifybackup可以检测到由于存储问题或用户错误而经常出现的许多问题。
备份验证分四个阶段进行。首先,pg_verifybackup
读取backup_manifest
文件。如果该文件不存在、无法读取、格式不正确或无法根据其内部校验和进行验证,pg_verifybackup
将以致命错误终止。
其次,pg_verifybackup
将尝试验证当前存储在磁盘上的数据文件是否与服务器打算发送的数据文件完全相同,下面将介绍一些例外情况。 除了少数例外,额外和丢失的文件将被检测到。此步骤将忽略 postgresql.auto.conf
、standby.signal
和 recovery.signal
的存在与否或对其的任何修改,因为预计这些文件可能是在备份过程中创建或修改的。它也不会抱怨目标目录中的 backup_manifest
文件或 pg_wal
中的任何内容,即使这些文件不会列在备份清单中。只检查文件;不验证目录的存在与否,除非间接验证:如果目录丢失,则它应该包含的任何文件也必然会丢失。
接下来,pg_verifybackup
将对所有文件进行校验和计算,将校验和与清单中的值进行比较,并对计算出的校验和与清单中存储的校验和不匹配的任何文件发出错误。对于在上一步中产生错误的任何文件,不执行此步骤,因为已知这些文件存在问题。在上一步中被忽略的文件在此步骤中也被忽略。
最后,pg_verifybackup
将使用清单来验证恢复备份所需的预写式日志记录是否存在,并且它们可以被读取和解析。 backup_manifest
包含有关需要哪些预写式日志记录的信息,并且 pg_verifybackup
将使用该信息来调用 pg_waldump
来解析这些预写式日志记录。 --quiet
标志将被使用,因此 pg_waldump
只会报告错误,而不会产生任何其他输出。虽然这种级别的验证足以检测明显的问题,例如丢失的文件或内部校验和不匹配的问题,但它们还不足以检测尝试恢复时可能出现的所有问题。例如,此方法无法检测到产生具有正确校验和但指定无意义操作的预写式日志记录的服务器错误。
请注意,如果存在不需要恢复备份的额外 WAL 文件,则此工具不会检查它们,尽管可以为此使用单独的 pg_waldump
调用。 另请注意,WAL 验证是特定于版本的:您必须使用 pg_verifybackup
的版本,因此是 pg_waldump
的版本,它与正在检查的备份有关。 相比之下,数据文件完整性检查应适用于生成 backup_manifest
文件的任何版本的服务器。
选项
pg_verifybackup 接受以下命令行参数:
-e
--exit-on-error
检测到备份问题后立即退出。 如果没有指定这个选项,
pg_verifybackup
将在检测到问题后继续检查备份,并将检测到的所有问题报告为错误。-i *
path*
--ignore=*
path*
本人提供Oracle、MySQL、PG等数据库的培训和考证业务,私聊QQ646634621或微信db_bao,谢谢!在将备份中实际存在的数据文件列表与
backup_manifest
文件中列出的数据文件列表进行比较时,忽略指定的文件或目录,该文件或目录应表示为相对路径名。如果指定了目录,则此选项会影响以该位置为根的整个子树。 如果相对路径名与指定的路径名匹配,有关额外文件、丢失文件、文件大小差异或校验和不匹配的投诉将被抑制。 可以多次指定此选项。-m *
path*
--manifest-path=*
path*
使用指定路径的清单文件,而不是位于备份目录根目录中的清单文件。
-n
--no-parse-wal
不要试图解析从该备份恢复所需的预写式日志数据。
-q
--quiet
成功验证备份后不要打印任何内容。
-s
--skip-checksums
不要验证数据文件校验和。但仍检查是否存在文件以及这些文件的大小。这样将会快得多,因为文件本身不需要读取。
-w *
path*
--wal-directory=*
path*
尝试解析存储在指定目录中的 WAL 文件,而不是
pg_wal
。 如果备份存储在与WAL存档不同的位置,则这可能很有用。
其他选项也可用:
-V
--version
打印 pg_verifybackup 版本并退出。
-?
--help
显示有关pg_verifybackup命令行参数的帮助,然后退出。
示例
要在 mydbserver
上创建服务器的基本备份并验证备份的完整性:
1 2 | $ pg_basebackup -h mydbserver -D /usr/local/pgsql/data $ pg_verifybackup /usr/local/pgsql/data |
要在 mydbserver
上创建服务器的基本备份,请将清单移动到备份目录之外的某个位置,并验证备份:
1 2 3 | $ pg_basebackup -h mydbserver -D /usr/local/pgsql/backup1234 $ mv /usr/local/pgsql/backup1234/backup_manifest /my/secure/location/backup_manifest.1234 $ pg_verifybackup -m /my/secure/location/backup_manifest.1234 /usr/local/pgsql/backup1234 |
要在忽略手动添加到备份目录的文件的同时验证备份,并跳过校验和验证:
1 2 3 | $ pg_basebackup -h mydbserver -D /usr/local/pgsql/data $ edit /usr/local/pgsql/data/note.to.self $ pg_verifybackup --ignore=note.to.self --skip-checksums /usr/local/pgsql/data |