MySQL备份与恢复策略
MySQL 是业务系统中最常见的数据库,但用好它并不容易。索引设计、SQL 优化、事务处理都是日常开发中需要关注的点。本文从实际场景出发,讲常见问题和解决思路。
一、备份类型
#
1.1 按备份方式
| 类型 |
说明 |
工具 |
| 逻辑备份 |
导出SQL语句 |
mysqldump, mydumper |
| 物理备份 |
复制数据文件 |
XtraBackup, mysqlbackup |
#
1.2 按备份范围
| 类型 |
说明 |
适用场景 |
| 全量备份 |
备份所有数据 |
基础备份 |
| 增量备份 |
备份变化的数据 |
减少备份时间和空间 |
| 差异备份 |
备份自上次全备以来的变化 |
平衡全备和增备 |
#
1.3 按备份状态
| 类型 |
说明 |
特点 |
| 热备 |
不停止服务 |
对业务影响小,需要工具支持 |
| 温备 |
只读备份 |
影响写入 |
| 冷备 |
停止服务 |
最简单,影响最大 |
二、mysqldump逻辑备份
#
2.1 基本用法
mysqldump -u root -p mydb > mydb.sql
mysqldump -u root -p --databases db1 db2 > databases.sql
mysqldump -u root -p --all-databases > all_databases.sql
mysqldump -u root -p mydb table1 table2 > tables.sql
|
#
2.2 常用参数
mysqldump -u root -p \ --single-transaction \ --master-data=2 \ --triggers \ --routines \ --events \ --databases mydb > mydb.sql
|
#
2.3 压缩备份
mysqldump -u root -p mydb | gzip > mydb.sql.gz
gunzip < mydb.sql.gz | mysql -u root -p mydb
|
#
2.4 恢复
mysql -u root -p mydb < mydb.sql
mysql -u root -p < all_databases.sql
pv mydb.sql | mysql -u root -p mydb
|
三、XtraBackup物理备份
#
3.1 为什么选择XtraBackup
| 特性 |
mysqldump |
XtraBackup |
| 备份速度 |
慢(逐行导出) |
快(文件复制) |
| 恢复速度 |
慢(逐行插入) |
快(文件复制) |
| 对业务影响 |
大(锁表或长事务) |
小(热备份) |
| 文件大小 |
大(文本SQL) |
小(数据文件) |
| 使用场景 |
小库、部分表 |
大库、全库 |
#
3.2 安装
yum install percona-xtrabackup-80
apt-get install percona-xtrabackup-80
|
#
3.3 全量备份
xtrabackup --backup \ --target-dir=/backup/full/$(date +%Y%m%d) \ --user=root --password=password
|
#
3.4 准备备份(Prepare)
xtrabackup --prepare --target-dir=/backup/full/20240728
|
#
3.5 增量备份
xtrabackup --backup \ --target-dir=/backup/inc1 \ --incremental-basedir=/backup/full/20240728 \ --user=root --password=password
xtrabackup --backup \ --target-dir=/backup/inc2 \ --incremental-basedir=/backup/inc1 \ --user=root --password=password
|
#
3.6 恢复
systemctl stop mysqld
mv /var/lib/mysql /var/lib/mysql_bak mkdir /var/lib/mysql
xtrabackup --copy-back --target-dir=/backup/full/20240728
xtrabackup --prepare \ --target-dir=/backup/full/20240728 \ --incremental-dir=/backup/inc1
xtrabackup --prepare \ --target-dir=/backup/full/20240728 \ --incremental-dir=/backup/inc2
chown -R mysql:mysql /var/lib/mysql
systemctl start mysqld
|
四、备份策略设计
#
4.1 3-2-1备份原则
#
4.2 备份周期设计
| 备份类型 |
频率 |
保留时间 |
| 全量备份 |
每周一次 |
1个月 |
| 增量备份 |
每天一次 |
1周 |
| binlog备份 |
实时 |
7-14天 |
#
4.3 自动化备份脚本
#!/bin/bash
BACKUP_DIR="/backup/mysql" DATE=$(date +%Y%m%d) WEEK_DAY=$(date +%u) MYSQL_USER="backup" MYSQL_PASS="password"
if [ "$WEEK_DAY" -eq 7 ]; then BACKUP_TYPE="full" TARGET_DIR="$BACKUP_DIR/full/$DATE" mkdir -p $TARGET_DIR xtrabackup --backup \ --target-dir=$TARGET_DIR \ --user=$MYSQL_USER --password=$MYSQL_PASS \ 2>$TARGET_DIR/backup.log echo $TARGET_DIR > $BACKUP_DIR/last_full.txt else BACKUP_TYPE="incremental" TARGET_DIR="$BACKUP_DIR/inc/$DATE" mkdir -p $TARGET_DIR FULL_DIR=$(cat $BACKUP_DIR/last_full.txt) if [ "$WEEK_DAY" -eq 1 ]; then BASE_DIR=$FULL_DIR else BASE_DIR=$(ls -td $BACKUP_DIR/inc/*/ | head -1) fi xtrabackup --backup \ --target-dir=$TARGET_DIR \ --incremental-basedir=$BASE_DIR \ --user=$MYSQL_USER --password=$MYSQL_PASS \ 2>$TARGET_DIR/backup.log fi
tar czf $TARGET_DIR.tar.gz -C $(dirname $TARGET_DIR) $(basename $TARGET_DIR) rm -rf $TARGET_DIR
aliyun oss cp $TARGET_DIR.tar.gz oss://mybucket/mysql-backup/
find $BACKUP_DIR -name "*.tar.gz" -mtime +30 -delete
echo "备份完成: $TARGET_DIR.tar.gz"
|
五、基于binlog的时点恢复
#
5.1 为什么需要binlog恢复
全量备份只能恢复到备份时刻。binlog记录了备份后的所有变更,可以实现任意时间点的恢复。
#
5.2 备份binlog
mysqlbinlog --read-from-remote-server \ --host=master --user=repl --password=password \ --raw --stop-never mysql-bin.000001 &
|
#
5.3 恢复流程
mysqlbinlog --start-datetime='2024-07-28 10:00:00' \ --stop-datetime='2024-07-28 12:00:00' \ /var/lib/mysql/mysql-bin.000005 | grep -i "DROP TABLE"
xtrabackup --copy-back --target-dir=/backup/full/20240728
mysqlbinlog --start-position=4 \ --stop-position=1234567 \ /var/lib/mysql/mysql-bin.000005 | mysql -u root -p
mysqlbinlog --start-position=1234580 \ /var/lib/mysql/mysql-bin.000005 | mysql -u root -p
|
#
5.4 基于时间恢复
mysqlbinlog --start-datetime='2024-07-28 00:00:00' \ --stop-datetime='2024-07-28 10:30:00' \ mysql-bin.000001 mysql-bin.000002 | mysql -u root -p
|
六、mydumper多线程备份
#
6.1 安装
git clone https://github.com/mydumper/mydumper.git cd mydumper cmake . make && make install
|
#
6.2 备份
mydumper -u root -p password \ -B mydb \ -o /backup/mydumper/$(date +%Y%m%d) \ -t 4 \ -c \ -G \ -E \ -R
|
#
6.3 恢复
myloader -u root -p password \ -d /backup/mydumper/20240728 \ -t 4 \ -B mydb
|
七、备份验证
#
7.1 定期恢复演练
FULL_BACKUP="/backup/full/latest" TEST_DIR="/var/lib/mysql_test"
xtrabackup --prepare --target-dir=$FULL_BACKUP
rm -rf $TEST_DIR mkdir $TEST_DIR xtrabackup --copy-back --target-dir=$FULL_BACKUP --datadir=$TEST_DIR
mysqld --datadir=$TEST_DIR --port=3307 --socket=/tmp/mysql_test.sock &
mysql -S /tmp/mysql_test.sock -e "CHECKSUM TABLE mydb.important_table"
mysqladmin -S /tmp/mysql_test.sock shutdown
echo "备份验证完成"
|
#
7.2 监控备份状态
BACKUP_SIZE=$(du -sm /backup/full/latest | awk '{print $1}') if [ $BACKUP_SIZE -lt 100 ]; then echo "备份文件异常小,可能备份失败" | mail -s "备份告警" dba@company.com fi
if grep -q "completed OK" /backup/full/latest/backup.log; then echo "备份成功" else echo "备份失败" | mail -s "备份告警" dba@company.com fi
|
八、云数据库备份
#
8.1 阿里云RDS
- 自动全量备份(每天)
- 自动增量备份(binlog,5分钟)
- 支持恢复到任意时间点
- 支持跨地域备份
#
8.2 腾讯云CDB
- 自动备份策略可配置
- 支持物理备份和逻辑备份
- 支持备份下载
九、灾难恢复计划
#
9.1 RPO和RTO
| 指标 |
说明 |
目标 |
| RPO |
恢复点目标,可接受的数据丢失量 |
< 5分钟 |
| RTO |
恢复时间目标,业务恢复所需时间 |
< 30分钟 |
#
9.2 恢复流程
灾难发生 │ ├── 评估损失范围 │ ├── 数据损坏 → 从备份恢复 │ └── 硬件故障 → 切换到备库 │ ├── 确定恢复时间点 │ └── 根据RPO选择binlog恢复点 │ ├── 执行恢复 │ ├── 恢复全备 │ ├── 应用增量备 │ └── 应用binlog │ ├── 验证数据完整性 │ └── 关键表校验 │ └── 切换业务流量
|
十、总结
| 备份方式 |
适用场景 |
优点 |
缺点 |
| mysqldump |
小库、部分表、迁移 |
简单、可读 |
慢、大 |
| XtraBackup |
大库、生产环境 |
快、热备 |
需要安装 |
| mydumper |
大库并行备份 |
多线程快 |
需安装 |
| binlog |
时点恢复 |
精确恢复 |
依赖全备 |
| 备份策略 |
频率 |
保留 |
| 全量备份 |
每周 |
1月 |
| 增量备份 |
每天 |
1周 |
| binlog |
实时 |
2周 |
备份的核心原则:
- 定期备份,自动化执行
- 备份加密,安全存储
- 异地容灾,防止单点
- 定期演练,验证可用
- 监控告警,及时发现问题
核心要点
索引设计的原则:最左前缀原则、避免索引列参与计算、选择合适的索引类型
SQL 优化的方法:使用 EXPLAIN 分析执行计划、避免 SELECT *、优化 JOIN
事务隔离级别的选择:根据业务需求选择合适的级别
常见的锁问题:行锁、表锁、死锁的处理
总结
MySQL 优化是一个持续的过程,需要结合业务特点和数据量来调整。在实际项目中,定期分析慢查询日志、优化索引、调整配置参数,都能提升数据库性能。