备份与恢复

数据库备份是保证数据安全的最后一道防线。MySQL 提供了多种备份和恢复方案,本节将详细介绍各种备份方法的原理、使用场景和最佳实践。

备份方式对比

备份方式 备份类型 数据完整性 备份速度 恢复速度 适用场景
mysqldump 逻辑备份 小数据量、开发测试
mysqlpump 逻辑备份 中等数据量
mydumper 逻辑备份 大数据量、并行备份
xtrabackup 物理备份 生产环境、大数据量
复制备份 物理备份 最快 高可用架构
binlog备份 增量备份 Point-in-time恢复

1. mysqldump 逻辑备份

mysqldump 是 MySQL 自带的逻辑备份工具,通过 SELECT 语句导出数据,生成 SQL 脚本。

flowchart LR
    A[MySQL Server] --> B[mysqldump]
    B --> C[.sql 文件]
    C --> D[CREATE TABLE 语句]
    C --> E[INSERT 语句]
    C --> F[数据]
    
    style A fill:#e3f2fd,stroke:#1565c0
    style B fill:#fff3e0,stroke:#e65100
    style C fill:#c8e6c9,stroke:#2e7d32
# 1. 备份单个数据库
mysqldump -u root -p mydb > mydb_backup.sql

# 2. 备份多个数据库
mysqldump -u root -p --databases db1 db2 > multi_db_backup.sql

# 3. 备份所有数据库
mysqldump -u root -p --all-databases > all_db_backup.sql

# 4. 备份指定表
mysqldump -u root -p mydb users orders > tables_backup.sql

# 5. 只备份表结构(不包含数据)
mysqldump -u root -p --no-data mydb > mydb_schema.sql

# 6. 只备份数据(不包含表结构)
mysqldump -u root -p --no-create-info mydb > mydb_data.sql

# 7. 备份远程数据库
mysqldump -h remote_host -u root -p mydb > remote_backup.sql

# 8. 压缩备份(节省磁盘空间)
mysqldump -u root -p mydb | gzip > mydb_backup.sql.gz

# 9. 定时自动备份脚本
# 添加到 crontab
0 2 * * * mysqldump -u root -p'mypassword' mydb | gzip > /backup/mydb_$(date +\%Y\%m\%d).sql.gz
# mysqldump 高级选项

# 1. 添加 DROP TABLE 语句(恢复时先删除旧表)
mysqldump -u root -p --add-drop-table mydb > backup.sql

# 2. 添加 CREATE DATABASE 语句
mysqldump -u root -p --add-drop-database mydb > backup.sql

# 3. 完全禁用外键检查(加快恢复速度)
mysqldump -u root -p --add-drop-table --disable-keys mydb > backup.sql

# 4. 备份触发器、存储过程、函数
mysqldump -u root -p --routines --triggers --functions mydb > backup.sql

# 5. 备份事件和视图
mysqldump -u root -p --events --views mydb > backup.sql

# 6. 使用 extended-insert 减少 SQL 语句数量
mysqldump -u root -p --extended-insert mydb > backup.sql

# 7. 导出事务安全的备份(用于 InnoDB)
mysqldump -u root -p --single-transaction --master-data=2 mydb > backup.sql

# 8. 锁表备份(用于 MyISAM)
mysqldump -u root -p --lock-tables --read-only mydb > backup.sql

# 9. 备份时刷新日志
mysqldump -u root -p --flush-logs mydb > backup.sql

# 10. 完整选项组合示例
mysqldump -u root -p \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --master-data=2 \
    --flush-logs \
    --add-drop-database \
    --add-drop-table \
    mydb > full_backup.sql

2. mysqldump 恢复

# 1. 恢复整个数据库
mysql -u root -p mydb < mydb_backup.sql

# 2. 恢复压缩的备份
gunzip < mydb_backup.sql.gz | mysql -u root -p

# 3. 恢复指定数据库(从全量备份中)
mysql -u root -p mydb < all_db_backup.sql

# 4. 恢复单个表
mysql -u root -p mydb < backup_with_tables.sql
# 或者使用 SOURCE 命令
mysql -u root -p mydb
SOURCE /path/to/backup.sql;

# 5. 恢复时忽略错误继续执行
mysql -u root -p --force mydb < backup.sql

# 6. 恢复时显示详细进度
mysql -u root -p -v mydb < backup.sql

# 7. 恢复并记录日志
mysql -u root -p mydb < backup.sql 2>&1 | tee restore.log

3. xtrabackup 物理备份

xtrabackup 是 Percona 开发的开源物理备份工具,支持在线热备份,性能优于 mysqldump。

flowchart TD
    A[开始备份] --> B[拷贝InnoDB数据文件]
    B --> C[记录LSN]
    C --> D[后台拷贝 redo log]
    D --> E[锁表拷贝非InnoDB表]
    E --> F[记录binlog位置]
    F --> G[准备备份]
    G --> H[应用事务日志]
    H --> I[生成备份]
    
    style A fill:#e3f2fd,stroke:#1565c0
    style I fill:#c8e6c9,stroke:#2e7d32
# 1. 安装 xtrabackup(CentOS/RHEL)
yum install percona-xtrabackup

# 2. 完全备份
xtrabackup --backup \
    --target-dir=/backup/full \
    --user=root \
    --password=yourpassword

# 3. 准备备份(恢复前必须执行)
xtrabackup --prepare \
    --target-dir=/backup/full

# 4. 恢复数据
systemctl stop mysql
xtrabackup --copy-back \
    --target-dir=/backup/full \
    --user=root \
    --password=yourpassword
chown -R mysql:mysql /var/lib/mysql
systemctl start mysql

# 5. 增量备份
# 先做完全备份
xtrabackup --backup --target-dir=/backup/base

# 基于完全备份做增量备份
xtrabackup --backup \
    --target-dir=/backup/inc1 \
    --incremental-basedir=/backup/base

# 6. 增量备份准备
xtrabackup --prepare --apply-log-only --target-dir=/backup/base
xtrabackup --prepare --incremental-dir=/backup/inc1 --target-dir=/backup/base

# 7. 压缩备份
xtrabackup --backup \
    --compress \
    --target-dir=/backup/compressed \
    --user=root --password=yourpassword

# 8. 加密备份
xtrabackup --backup \
    --encrypt=AES256 \
    --encrypt-key-file=/backup/keyfile \
    --target-dir=/backup/encrypted \

4. binlog 增量备份与时间点恢复

binlog 记录了所有数据变更操作,结合全量备份可以实现任意时间点恢复(PITR)。

binlog 格式 说明 优缺点
STATEMENT 记录SQL语句 日志量小,但有不确定性函数
ROW 记录行数据变化 日志量大,但最可靠
MIXED 混合模式 平衡选项,推荐使用
# 1. 查看 binlog 是否开启
SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';

# 2. 查看 binlog 文件列表
SHOW BINARY LOGS;

# 3. 查看当前 binlog 位置
SHOW MASTER STATUS;

# 4. 查看 binlog 事件
SHOW BINLOG EVENTS IN 'mysql-bin.000001';

# 5. 使用 mysqlbinlog 查看 binlog 内容
mysqlbinlog mysql-bin.000001 | head -50

# 6. 查看特定时间段的 binlog
mysqlbinlog --start-datetime="2024-01-15 10:00:00" \
    --stop-datetime="2024-01-15 12:00:00" \
    mysql-bin.000001

# 7. 导出 binlog 为 SQL
mysqlbinlog mysql-bin.000001 > binlog.sql

# 8. 基于 position 恢复
mysqlbinlog --start-position=1234 --stop-position=5678 mysql-bin.000001 | mysql -u root -p

# 9. 恢复到指定时间点
mysqlbinlog --stop-datetime="2024-01-15 11:30:00" mysql-bin.000001 | mysql -u root -p

# 10. 定期清理 binlog(保留7天)
PURGE BINARY LOGS BEFORE DATE(NOW() - INTERVAL 7 DAY);

5. Point-in-Time Recovery (PITR) 实践

flowchart LR
    A[全量备份] --> B[恢复全量备份]
    B --> C[应用binlog]
    C --> D[恢复到指定时间点]
    
    style A fill:#e3f2fd,stroke:#1565c0
    style D fill:#c8e6c9,stroke:#2e7d32
# PITR 恢复步骤示例

# 步骤1:查找需要恢复的时间点和 binlog 位置
# 假设用户在 2024-01-15 14:30:00 误删除了数据
# 需要恢复到 2024-01-15 14:25:00

# 步骤2:恢复最新的全量备份
mysql -u root -p mydb < /backup/full_backup_20240115.sql

# 步骤3:应用 binlog 到指定时间点
mysqlbinlog --stop-datetime="2024-01-15 14:25:00" \
    mysql-bin.000001 \
    mysql-bin.000002 | mysql -u root -p mydb

# 步骤4:验证数据恢复成功
SELECT * FROM deleted_table WHERE id = 1;

# 高级:跳过有问题的 SQL
# 假设某个 DELETE 语句需要跳过
mysqlbinlog mysql-bin.000001 | grep -v "DELETE FROM" | mysql -u root -p

6. 主从复制备份策略

利用主从复制架构,可以从从库进行备份,避免影响主库性能。

# 1. 在从库上停止复制
STOP SLAVE;

# 2. 记录复制位置
SHOW SLAVE STATUS\G
# 记录 Relay_Master_Log_File 和 Exec_Master_Log_Pos

# 3. 从从库进行备份
mysqldump -u root -p --single-transaction mydb > slave_backup.sql

# 4. 重新启动复制
START SLAVE;

# 5. 或者使用 xtrabackup 在从库备份(热备份)
xtrabackup --backup --slave-info --target-dir=/backup/from_slave/

# 6. 从库备份信息文件内容示例:
# mysqlbinlog --start-position=12345 mysql-bin.000001 > to_replay.sql
# 表示从库备份后需要应用这些 binlog 来同步

7. 自动备份脚本示例

#!/bin/bash
# MySQL 自动备份脚本

# 配置变量
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_NAME="mydb"
DB_USER="root"
DB_PASS="yourpassword"
RETENTION_DAYS=7

# 创建备份目录
mkdir -p $BACKUP_DIR

# 执行备份
echo "Starting backup at $(date)"

# 逻辑备份
mysqldump -u $DB_USER -p$DB_PASS \
    --single-transaction \
    --routines \
    --triggers \
    --events \
    --master-data=2 \
    --flush-logs \
    $DB_NAME | gzip > $BACKUP_DIR/${DB_NAME}_${DATE}.sql.gz

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "Backup completed successfully"
    
    # 删除过期备份
    find $BACKUP_DIR -name "*.sql.gz" -mtime +$RETENTION_DAYS -delete
    
    # 记录备份信息
    echo "$(date) - Backup successful" >> $BACKUP_DIR/backup.log
else
    echo "Backup failed!"
    echo "$(date) - Backup FAILED" >> $BACKUP_DIR/backup.log
    exit 1
fi

# 添加到 crontab(每天凌晨2点执行)
# 0 2 * * * /path/to/backup.sh

8. 备份最佳实践

# 备份策略建议

-- 1. 3-2-1 备份法则
-- - 至少3份数据副本
-- - 存储在2种不同介质上
-- - 1份异地备份

-- 2. 备份频率建议
-- - 全量备份:每天或每周
-- - 增量备份:每小时或每几小时
-- - binlog:实时备份

-- 3. 备份验证
-- - 定期测试恢复流程
-- - 验证备份完整性
-- - 测试 Point-in-Time 恢复

-- 4. 备份监控
-- - 监控备份任务执行状态
-- - 监控备份文件大小变化
-- - 监控磁盘空间使用

-- 5. 安全建议
-- - 备份文件加密存储
-- - 限制备份目录访问权限
-- - 定期轮换备份密钥

9. 常见备份问题与解决方案

问题 原因 解决方案
备份文件过大 未压缩、冗余数据 使用压缩、增量备份
备份速度慢 单线程、网络延迟 使用 mydumper 并行备份
恢复失败 备份不完整、外键冲突 使用 --force、禁用外键检查
binlog 损坏 磁盘故障、未刷新 定期 PURGE、配置双写
备份丢失 单点存储、误删除 异地备份、多副本