测试恢复结果
无法恢复的备份毫无用处。
测试恢复结果 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 3 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。
无法恢复的备份毫无价值
许多团队投入时间设置自动备份,却从不验证这些备份是否真的可用于恢复数据。恢复过程中失败的备份根本算不上备份。
本课将介绍恢复测试的规范流程:在真正的灾难迫使您付出惨痛代价之前,验证备份是否有效。
恢复测试包括哪些内容
恢复测试包括获取一个备份文件并将其加载到数据库中——通常是单独的测试实例——然后查询该数据库,以确认数据完整且一致。
步骤如下:1) 获取备份文件。2) 将其恢复到沙箱环境。3) 运行验证查询。4) 将结果与生产环境进行比较。
创建用于比较的基线快照
在验证恢复结果之前,您需要一个基线——一组来自生产环境的已知计数和校验和,用于与恢复后的副本进行比较。
在生产数据库上运行此查询并记录结果:
SELECT
'orders' AS tbl, COUNT(*) AS row_count FROM orders
UNION ALL
SELECT
'customers' AS tbl, COUNT(*) AS row_count FROM customers
UNION ALL
SELECT
'order_items' AS tbl, COUNT(*) AS row_count FROM order_items;验证恢复后的行数
备份恢复到测试数据库后,运行相同的查询并比较数字。如果计数一致,说明恢复的基本结构是健康的。
这里的不匹配会立即告诉您,数据在备份或恢复期间丢失了——而您甚至还没有接触生产环境。
-- Run on the RESTORED test database
SELECT
'orders' AS tbl, COUNT(*) AS row_count FROM orders
UNION ALL
SELECT
'customers' AS tbl, COUNT(*) AS row_count FROM customers
UNION ALL
SELECT
'order_items' AS tbl, COUNT(*) AS row_count FROM order_items;检查最新数据
行数可以确认数量,但不能确认时效性。请检查恢复后的数据库是否包含最近的记录——备份应反映截至创建时刻的数据。
SELECT
MAX(created_at) AS latest_order,
MIN(created_at) AS oldest_order,
COUNT(*) AS total_orders
FROM orders;验证引用完整性
即使行数一致,恢复仍可能留下孤立行——也就是父记录不再存在的子记录。这通常发生在备份或恢复期间未强制执行外键时。
使用 LEFT JOIN 检测孤立的订单项:
SELECT
oi.id AS orphaned_item_id,
oi.order_id AS missing_order_id
FROM order_items oi
LEFT JOIN orders o ON o.id = oi.order_id
WHERE o.id IS NULL;使用校验和检测损坏
对于关键表,请生成数据校验和,以检测位级损坏。在 PostgreSQL 中,您可以将 MD5 与整行的类型转换结合使用。
如果生产环境和恢复后的副本的校验和不同,说明数据在某个时刻被修改或损坏。
SELECT
MD5(string_agg(row_data, ',' ORDER BY row_data)) AS table_checksum
FROM (
SELECT CAST(ROW(id, customer_id, total, created_at) AS TEXT) AS row_data
FROM orders
) sub;创建恢复验证表
为了跟踪恢复测试的历史记录,请创建专用的恢复验证日志表。记录每次测试运行的备份日期、恢复后的行数,以及验证是否通过。
CREATE TABLE IF NOT EXISTS restore_validation_log (
id SERIAL PRIMARY KEY,
backup_taken_at TIMESTAMP NOT NULL,
restored_at TIMESTAMP NOT NULL DEFAULT NOW(),
table_name VARCHAR(100) NOT NULL,
expected_rows INT NOT NULL,
actual_rows INT NOT NULL,
passed BOOLEAN NOT NULL
);插入验证结果
每次恢复测试后,向验证日志中插入一行。这样可以提供审计轨迹,证明备份经过测试,并显示一段时间内通过或失败的模式。
INSERT INTO restore_validation_log
(backup_taken_at, table_name, expected_rows, actual_rows, passed)
VALUES
('2024-06-09 02:00:00', 'orders', 15482, 15482, TRUE),
('2024-06-09 02:00:00', 'customers', 8201, 8201, TRUE),
('2024-06-09 02:00:00', 'order_items', 47310, 47310, TRUE);查询验证历史记录
请定期查看验证日志,以发现任何退化。上周通过但本周失败的备份表明备份流水线存在问题,必须立即调查。
SELECT
backup_taken_at,
table_name,
expected_rows,
actual_rows,
passed,
CASE
WHEN passed THEN 'OK'
ELSE 'MISMATCH - investigate!'
END AS status
FROM restore_validation_log
ORDER BY backup_taken_at DESC, table_name;时间点恢复验证
现代数据库支持时间点恢复(PITR),您可以使用基础备份加上 WAL(预写日志)归档,将数据库恢复到任意时刻。
要验证 PITR 正常工作,请恢复到一个已知时间戳,并检查在该时间戳之后创建的记录在恢复后的数据库中 NOT 出现:
-- After a PITR restore to '2024-06-09 03:00:00',
-- this order (created at 03:45) should NOT exist:
SELECT id, created_at, total
FROM orders
WHERE created_at > '2024-06-09 03:00:00'
ORDER BY created_at
LIMIT 5;
-- Zero rows = PITR worked correctly快速检查
恢复备份后,以下哪条查询最适合检测孤立的子记录?
课程回顾:测试恢复结果
在本课中,您学习了为什么恢复测试是任何备份策略中不可或缺的一部分,以及如何使用 SQL 实现恢复测试:
- 基线快照 — 在测试前记录生产环境的行数。
- 行数比较 — 在恢复后的数据库上运行相同的查询并进行比较。
- 时效性检查 — 确认最新记录与预期的备份时间范围一致。
- 引用完整性 — 使用 LEFT JOIN 查找孤立的子行。
- 校验和验证 — 使用 MD5 聚合检测位级损坏。
- 验证日志表 — 跟踪每次测试运行,形成可审计的历史记录。
- PITR 验证 — 确认时间点恢复在正确时刻完成。
备份是否可靠,取决于上一次成功的恢复测试。请定期安排这些检查,并将任何失败视为严重事件。
常见问题解答
「测试恢复结果」课时是免费的吗?
是的 — 「测试恢复结果」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。
「测试恢复结果」这节课中我会学到什么?
无法恢复的备份毫无用处。 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 3 节课,共 4 节。
「测试恢复结果」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Academy 课中编写并运行代码吗?
能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。