数据库恢复技术当灾难来临一句话总结数据库通过事务日志Undo/Redo 日志、检查点Checkpoint和定期备份构建了三重恢复防线能在事务故障、系统故障和介质故障后将数据恢复到一致、正确、可用的状态。一、为什么数据库需要恢复数据库运行在生产环境中随时可能面临各种故障故障类型场景影响事务故障程序逻辑错误、用户主动回滚事务未正常完成部分修改已写入数据库系统故障断电、操作系统崩溃、CPU 故障内存中数据丢失已提交事务可能未刷盘介质故障硬盘损坏、磁盘坏道、存储设备故障磁盘数据丢失或损坏人为故障误删数据、误删表、误执行 DROP DATABASE数据被意外删除或修改如果没有恢复机制任何一次故障都可能是灾难性的。数据库恢复技术就是数据安全的最后一道防线。二、恢复的基本原理冗余数据库恢复的核心思想是冗余——通过保存数据的副本在故障发生后用副本来恢复。2.1 两种冗余手段手段内容用途数据转储备份定期复制数据库到另一介质介质故障后恢复完整数据日志文件记录所有事务的操作故障后根据日志 redo/undo2.2 数据转储备份的类型备份类型英文说明恢复速度空间占用全量备份Full Backup备份整个数据库最快最大增量备份Incremental Backup只备份上次备份后变化的数据中等较小差异备份Differential Backup备份上次全量备份后变化的数据中等中等备份策略推荐每周一次全量备份 每天一次增量备份。三、事务日志数据库的黑匣子日志文件Log File是数据库恢复的核心它记录了数据库中所有事务的操作。就像飞机的黑匣子能在事故后还原整个过程。3.1 日志记录的内容每条日志记录通常包含事务标识Transaction ID操作类型BEGIN, COMMIT, ROLLBACK, UPDATE, INSERT, DELETE操作对象表名、行号、列名修改前数据Old Value修改后数据New Value3.2 日志的两类用途日志类型作用场景Undo 日志撤销未提交事务的修改事务故障、系统故障后恢复Redo 日志重做已提交事务的修改系统故障后恢复已提交但数据在内存中未刷盘3.3 日志的工作流程-- 事务执行过程日志同步记录BEGIN;-- 日志BEGIN T1UPDATE账户SET余额900WHERE账户A;-- 日志T1, UPDATE A, 1000→900UPDATE账户SET余额1100WHERE账户B;-- 日志T1, UPDATE B, 1000→1100COMMIT;-- 日志COMMIT T1日志是**先写日志Write-Ahead Log, WAL**原则在数据写入磁盘之前先写入日志。这是数据库恢复的关键保证。四、故障恢复策略4.1 事务故障恢复原因事务执行到一半出错或用户主动执行 ROLLBACK。恢复方法反向扫描日志找到该事务的所有操作执行逆操作Undo。日志BEGIN T1 → UPDATE A: 1000→900 → UPDATE B: 1000→1100 → (事务崩溃无 COMMIT) 恢复Undo T1 1. 将 A 恢复为 1000Undo UPDATE A 2. 将 B 恢复为 1000Undo UPDATE B4.2 系统故障恢复原因断电、系统崩溃内存中数据丢失。恢复方法扫描日志找到所有已提交事务有 BEGIN 和 COMMIT执行Redo找到所有未提交事务有 BEGIN 无 COMMIT执行Undo日志 BEGIN T1 → UPDATE A → COMMIT T1 BEGIN T2 → UPDATE B → (系统崩溃无 COMMIT) BEGIN T3 → UPDATE C → COMMIT T3 恢复 Redo T1确保 A 的修改已写入磁盘 Undo T2将 B 恢复为原值 Redo T3确保 C 的修改已写入磁盘4.3 介质故障恢复原因硬盘损坏、磁盘故障。恢复方法装入最新全量备份恢复数据库到备份时刻的状态装入后续增量备份如果有扫描日志对备份后提交的事务执行Redo介质故障恢复是唯一的需要备份的场景。事务故障和系统故障只依赖日志即可。五、检查点加速恢复的关键5.1 为什么要检查点如果数据库运行了一年日志文件可能有几 GB。故障恢复时需要扫描全部日志耗时极长。检查点Checkpoint是 DBMS 定期执行的一个操作将内存中所有已提交事务的修改强制刷盘并在日志中记录一个检查点标记。5.2 检查点的工作流程将日志缓冲区中的所有日志写入磁盘将数据缓冲区中所有已提交事务的修改写入磁盘在日志中写入CHECKPOINT记录记录当前活跃事务列表尚未提交的事务5.3 检查点如何加速恢复日志... [T1 BEGIN] [T1 COMMIT] ... [T2 BEGIN] [T3 BEGIN] [CHECKPOINT] ... [T2 COMMIT] ... [系统故障] 恢复策略 - 检查点之前的已提交事务如 T1修改已刷盘无需 Redo - 检查点之后的已提交事务如 T2需要 Redo - 检查点时活跃且未提交的事务如 T3需要 Undo有了检查点恢复时只需扫描最后一个检查点之后的日志而不是全部日志。5.4 检查点配置-- MySQL InnoDB 检查点配置通常自动管理SETGLOBALinnodb_flush_log_at_trx_commit1;-- 每次事务提交都刷日志最安全SETGLOBALinnodb_flush_log_at_trx_commit2;-- 每秒刷一次日志性能更好六、数据库备份实战6.1 MySQL 备份与恢复全量备份mysqldump# 备份单个数据库mysqldump-uroot-p学校数据库school_backup.sql# 备份所有数据库mysqldump-uroot-p--all-databasesall_databases_backup.sql# 只备份表结构mysqldump-uroot-p--no-data 学校数据库school_schema.sql恢复# 恢复数据库mysql-uroot-p学校数据库school_backup.sql物理备份InnoDB 冷备份# 1. 停止 MySQLsudosystemctl stop mysql# 2. 复制数据目录cp-r/var/lib/mysql /backup/mysql_$(date%Y%m%d)# 3. 启动 MySQLsudosystemctl start mysql6.2 PostgreSQL 备份与恢复# 备份pg_dump-Upostgres-Fc学校数据库school.dump# 恢复pg_restore-Upostgres-d学校数据库 school.dump6.3 自动化备份脚本#!/bin/bash# 每天凌晨 3 点自动备份 MySQLDATE$(date%Y%m%d_%H%M%S)BACKUP_DIR/backup/mysqlDB_NAMEschool# 创建备份目录mkdir-p$BACKUP_DIR# 执行备份mysqldump-ubackup_user -ppassword$DB_NAME$BACKUP_DIR/${DB_NAME}_${DATE}.sql# 删除 7 天前的备份find$BACKUP_DIR-name*.sql-mtime7-delete# 记录日志echo[$DATE] Backup completed:${DB_NAME}_${DATE}.sql/var/log/db_backup.log配合 cron 定时任务0 3 * * * /path/to/backup_script.sh七、恢复的最佳实践7.1 备份策略3-2-1 原则3 份备份至少保留 3 份数据副本2 种介质备份存放在至少 2 种不同介质上如本地磁盘 网络存储1 份异地至少 1 份备份放在异地防止火灾、洪水等灾害7.2 恢复演练备份不是目的能恢复才是。建议每季度进行一次恢复演练验证备份文件是否完整可用记录恢复时间评估是否满足 RTO恢复时间目标7.3 常见恢复场景场景恢复方案误删一条记录从 BinlogMySQL或 WALPostgreSQL中提取日志找到 DELETE 语句执行逆向 INSERT误删一张表从最新备份恢复再用日志 Redo 备份后的操作误删整个数据库从最新全量备份恢复再用日志 Redo硬盘损坏更换硬盘从异地备份恢复八、动手练习练习 1备份与恢复实验创建一个测试数据库插入若干数据用 mysqldump 备份删除数据库用备份文件恢复验证数据是否完整练习 2日志分析查看 MySQL 的 Binlog找到最近一条 UPDATE 语句的日志记录分析其结构。# 查看 binlog 列表mysql-uroot-p-eSHOW BINARY LOGS;# 查看 binlog 内容mysqlbinlog /var/lib/mysql/binlog.000001|grep-A5-B5UPDATE练习 3制定备份策略为以下系统制定备份策略说明备份频率、方式和保留周期一个日活 10 万的电商系统一个学校教务系统数据量小但重要性高九、常见误区与避坑指南误区正确理解“有 RAID 就不需要备份”RAID 防硬件故障不防误删、勒索病毒、逻辑错误“备份文件和数据库放同一个盘”磁盘损坏时备份和数据库一起丢失必须异地存储“只备份数据文件不备份日志”日志是恢复的关键特别是需要精确恢复到某一时刻时“备份做了就行不用验证”备份文件可能损坏必须定期恢复测试“Undo 和 Redo 是同一个东西”Undo 是撤销回滚Redo 是重做恢复方向相反十、下篇预告下一篇我们将学习存储过程与触发器——如何把常用的业务逻辑封装在数据库内部实现自动化处理和代码复用让数据库不只是存数据的仓库还能成为处理数据的引擎。