写在前面
大家好,欢迎来到MySQL全面教学系列的第14天。经过了前面13天的学习,我们已经掌握了MySQL的方方面面。今天,我们要聊一个DBA(数据库管理员)最关注的话题------备份与恢复。
有一个DBA段子:"删库跑路一时爽,牢饭吃到泪两行。"
虽然是个玩笑,但它提醒我们:数据是企业的生命线,备份是DBA的底线。没有备份的数据库,就像没有刹车的汽车,随时可能出大事。
今天,我将带你掌握MySQL备份恢复的完整技能,让你在面对数据灾难时能够从容应对。

目录
-
- 写在前面
- 一、为什么需要备份
-
- [1.1 真实案例:删库跑路的故事](#1.1 真实案例:删库跑路的故事)
- [1.2 数据丢失的常见原因](#1.2 数据丢失的常见原因)
- [1.3 备份的目标](#1.3 备份的目标)
- 二、备份类型
-
- [2.1 按备份内容分类](#2.1 按备份内容分类)
- [2.2 按备份方式分类](#2.2 按备份方式分类)
- [2.3 按备份状态分类](#2.3 按备份状态分类)
- [2.4 备份类型对比表](#2.4 备份类型对比表)
- 三、mysqldump(逻辑备份)
-
- [3.1 mysqldump简介](#3.1 mysqldump简介)
- [3.2 常用参数](#3.2 常用参数)
- [3.3 常用备份命令](#3.3 常用备份命令)
- [3.4 单表备份技巧](#3.4 单表备份技巧)
- [3.5 恢复数据](#3.5 恢复数据)
- [3.6 mysqldump的优缺点](#3.6 mysqldump的优缺点)
- 四、xtrabackup(物理热备份)
-
- [4.1 xtrabackup简介](#4.1 xtrabackup简介)
- [4.2 安装xtrabackup](#4.2 安装xtrabackup)
- [4.3 常用命令](#4.3 常用命令)
- [4.4 增量备份](#4.4 增量备份)
- [4.5 恢复数据](#4.5 恢复数据)
- [4.6 xtrabackup的优缺点](#4.6 xtrabackup的优缺点)
- 五、主从复制
-
- [5.1 主从复制架构](#5.1 主从复制架构)
- [5.2 主从复制的作用](#5.2 主从复制的作用)
- [5.3 搭建主从复制](#5.3 搭建主从复制)
- [5.4 读写分离](#5.4 读写分离)
- [5.5 主从延迟问题](#5.5 主从延迟问题)
- 六、数据恢复
-
- [6.1 全量恢复](#6.1 全量恢复)
- [6.2 时间点恢复(PITR)](#6.2 时间点恢复(PITR))
- [6.3 误删恢复](#6.3 误删恢复)
- 七、实战:制定备份策略
-
- [7.1 备份策略设计原则](#7.1 备份策略设计原则)
- [7.2 示例备份策略](#7.2 示例备份策略)
- [7.3 自动化备份脚本](#7.3 自动化备份脚本)
- [7.4 备份验证](#7.4 备份验证)
- 八、踩坑提醒
-
- [8.1 备份文件要定期验证](#8.1 备份文件要定期验证)
- [8.2 binlog_expire_logs_days设置](#8.2 binlog_expire_logs_days设置)
- [8.3 备份时的锁问题](#8.3 备份时的锁问题)
- [8.4 大表备份的坑](#8.4 大表备份的坑)
- [8.5 恢复时的字符集问题](#8.5 恢复时的字符集问题)
- 九、面试高频考点
-
- [9.1 mysqldump和xtrabackup的区别?](#9.1 mysqldump和xtrabackup的区别?)
- [9.2 主从延迟怎么解决?](#9.2 主从延迟怎么解决?)
- [9.3 如何实现零数据丢失?](#9.3 如何实现零数据丢失?)
- [9.4 误删数据如何恢复?](#9.4 误删数据如何恢复?)
- [9.5 如何设计备份策略?](#9.5 如何设计备份策略?)
- 十、总结
- 十一、下一步预告
- 参考资料
- 互动话题
一、为什么需要备份
1.1 真实案例:删库跑路的故事
案例1:某电商公司
- 时间:2020年某日凌晨
- 事件:运维人员误执行
DROP DATABASE production - 后果:3TB数据瞬间消失,无有效备份
- 损失:直接经济损失500万,公司濒临倒闭
案例2:某金融公司
- 时间:2021年
- 事件:勒索病毒攻击,数据库被加密
- 后果:虽然有备份,但备份文件也被加密
- 教训:备份要异地、离线存储
案例3:某社交平台
- 时间:2022年
- 事件:硬盘故障,RAID阵列损坏
- 结果:因为有完善的备份策略,2小时内恢复服务
- 启示:备份是最后的救命稻草
1.2 数据丢失的常见原因
| 原因类型 | 具体场景 | 发生频率 |
|---|---|---|
| 人为误操作 | DROP、DELETE不带WHERE、UPDATE错条件 | 高 |
| 程序BUG | 代码逻辑错误导致数据被删 | 高 |
| 硬件故障 | 硬盘损坏、服务器宕机 | 中 |
| 网络攻击 | 勒索病毒、黑客入侵 | 中 |
| 自然灾害 | 火灾、水灾、地震 | 低 |
| 软件故障 | MySQL崩溃、数据文件损坏 | 中 |
1.3 备份的目标
RPO(Recovery Point Objective):恢复点目标
- 定义:能恢复到多久以前的数据
- 目标:RPO越小越好,理想情况是0(实时备份)
RTO(Recovery Time Objective):恢复时间目标
- 定义:恢复服务需要多长时间
- 目标:RTO越小越好,关键系统要求分钟级
二、备份类型
2.1 按备份内容分类
| 备份类型 | 说明 | 优点 | 缺点 |
|---|---|---|---|
| 全量备份 | 备份所有数据 | 恢复简单 | 耗时、占用空间大 |
| 增量备份 | 只备份变化的数据 | 速度快、空间小 | 恢复复杂,依赖链 |
| 差异备份 | 备份自上次全量后的变化 | 平衡方案 | 随时间增长变大 |
2.2 按备份方式分类
| 备份方式 | 说明 | 工具 | 适用场景 |
|---|---|---|---|
| 逻辑备份 | 导出SQL语句 | mysqldump | 小数据量、跨版本 |
| 物理备份 | 复制数据文件 | xtrabackup、冷拷贝 | 大数据量、快速恢复 |
2.3 按备份状态分类
| 备份状态 | 说明 | 特点 |
|---|---|---|
| 热备份 | 不锁表,业务正常运行 | 对业务影响小,但复杂 |
| 温备份 | 只读锁,只能读不能写 | 平衡方案 |
| 冷备份 | 停服备份 | 简单,但影响业务 |
2.4 备份类型对比表
| 维度 | 逻辑备份(mysqldump) | 物理备份(xtrabackup) |
|---|---|---|
| 备份速度 | 慢 | 快 |
| 恢复速度 | 慢 | 快 |
| 备份大小 | 较小(文本压缩) | 较大(数据文件) |
| 是否锁表 | 是(默认) | 否(热备) |
| 跨版本 | 支持 | 不支持 |
| 适用规模 | <50GB | >50GB |
| 颗粒度 | 库、表级别 | 实例级别 |
| 学习成本 | 低 | 高 |
三、mysqldump(逻辑备份)
3.1 mysqldump简介
mysqldump是MySQL自带的逻辑备份工具,将数据导出为SQL语句。
3.2 常用参数
| 参数 | 说明 | 示例 |
|---|---|---|
-u |
用户名 | -u root |
-p |
密码(会提示输入) | -p |
-h |
主机地址 | -h 192.168.1.100 |
-P |
端口号 | -P 3306 |
--all-databases |
备份所有库 | -A |
--databases |
备份指定库 | -B db1 db2 |
--tables |
备份指定表 | db1 table1 table2 |
--single-transaction |
单事务备份(InnoDB不锁表) | 热备关键参数 |
--lock-all-tables |
锁定所有表 | -x |
--lock-tables |
锁定指定表 | -l |
--no-data |
只备份结构 | -d |
--no-create-info |
只备份数据 | -t |
--where |
条件备份 | --where="id<1000" |
--master-data |
记录binlog位置 | --master-data=2 |
--routines |
备份存储过程和函数 | -R |
--triggers |
备份触发器 | 默认开启 |
--events |
备份事件 | -E |
--compress |
压缩传输 | -C |
3.3 常用备份命令
bash
# 1. 备份单个数据库
mysqldump -u root -p mydb > mydb_backup.sql
# 2. 备份多个数据库
mysqldump -u root -p -B db1 db2 db3 > multi_db_backup.sql
# 3. 备份所有数据库
mysqldump -u root -p -A > all_databases_backup.sql
# 4. 备份单表
mysqldump -u root -p mydb users > users_backup.sql
# 5. 只备份结构(不包含数据)
mysqldump -u root -p -d mydb > mydb_schema.sql
# 6. 只备份数据(不包含结构)
mysqldump -u root -p -t mydb > mydb_data.sql
# 7. InnoDB热备(不锁表)
mysqldump -u root -p --single-transaction mydb > mydb_hot_backup.sql
# 8. 带binlog位置的备份(用于主从复制)
mysqldump -u root -p --single-transaction --master-data=2 mydb > mydb_backup.sql
# 9. 压缩备份
mysqldump -u root -p mydb | gzip > mydb_backup.sql.gz
# 10. 远程备份
mysqldump -u root -p -h 192.168.1.100 -P 3306 mydb > mydb_remote_backup.sql
3.4 单表备份技巧
bash
# 1. 备份指定表
mysqldump -u root -p mydb orders order_items > tables_backup.sql
# 2. 按条件备份(只备份近一年的数据)
mysqldump -u root -p mydb orders --where="create_time > DATE_SUB(NOW(), INTERVAL 1 YEAR)" > orders_recent.sql
# 3. 分表备份(大表拆分成多个文件)
mysqldump -u root -p mydb orders --where="id BETWEEN 1 AND 1000000" > orders_part1.sql
mysqldump -u root -p mydb orders --where="id BETWEEN 1000001 AND 2000000" > orders_part2.sql
3.5 恢复数据
bash
# 1. 恢复整个数据库
mysql -u root -p mydb < mydb_backup.sql
# 2. 恢复前创建数据库
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS mydb;"
mysql -u root -p mydb < mydb_backup.sql
# 3. 解压后恢复
gunzip < mydb_backup.sql.gz | mysql -u root -p mydb
# 4. 恢复单个表(从全库备份中提取)
# 先找到表的SQL语句,然后执行
# 5. 使用source命令(登录后执行)
mysql> CREATE DATABASE mydb;
mysql> USE mydb;
mysql> SOURCE /path/to/mydb_backup.sql;
3.6 mysqldump的优缺点
优点:
- 简单易用,学习成本低
- 文本格式,可读性好
- 跨版本、跨平台兼容
- 可以精细控制备份内容
缺点:
- 备份和恢复速度慢
- 大数据量时性能差
- 备份期间可能锁表
- 不支持增量备份
四、xtrabackup(物理热备份)
4.1 xtrabackup简介
Percona XtraBackup是Percona公司开发的开源热备份工具,支持InnoDB和XtraDB引擎的热备份(不锁表)。
4.2 安装xtrabackup
bash
# CentOS/RHEL
yum install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
percona-release enable-only tools release
yum install percona-xtrabackup-80
# Ubuntu/Debian
wget https://repo.percona.com/apt/percona-release_latest.$(lsb_release -sc)_all.deb
dpkg -i percona-release_latest.$(lsb_release -sc)_all.deb
percona-release enable-only tools release
apt-get update
apt-get install percona-xtrabackup-80
# 验证安装
xtrabackup --version
4.3 常用命令
bash
# 1. 全量备份
xtrabackup --backup --target-dir=/backup/full --user=root --password=your_password
# 2. 指定socket和端口
xtrabackup --backup --target-dir=/backup/full \
--socket=/var/lib/mysql/mysql.sock \
--user=root --password=your_password
# 3. 压缩备份
xtrabackup --backup --compress --target-dir=/backup/compressed \
--user=root --password=your_password
# 4. 流式备份到远程
xtrabackup --backup --stream=xbstream --target-dir=/tmp \
--user=root --password=your_password | ssh user@remote "xbstream -x -C /backup/"
# 5. 限速备份(避免影响业务)
xtrabackup --backup --target-dir=/backup/full \
--throttle=100 \
--user=root --password=your_password
4.4 增量备份
bash
# 第1步:全量备份(周日)
xtrabackup --backup --target-dir=/backup/full \
--user=root --password=your_password
# 第2步:周一增量备份
xtrabackup --backup --target-dir=/backup/inc1 \
--incremental-basedir=/backup/full \
--user=root --password=your_password
# 第3步:周二增量备份(基于周一)
xtrabackup --backup --target-dir=/backup/inc2 \
--incremental-basedir=/backup/inc1 \
--user=root --password=your_password
# 第4步:周三增量备份(基于周日全量)
xtrabackup --backup --target-dir=/backup/inc3 \
--incremental-basedir=/backup/full \
--user=root --password=your_password
4.5 恢复数据
bash
# 1. 准备全量备份(应用日志)
xtrabackup --prepare --target-dir=/backup/full
# 2. 准备增量备份(如果有)
# 先应用全量
xtrabackup --prepare --apply-log-only --target-dir=/backup/full
# 应用第一个增量
xtrabackup --prepare --apply-log-only --target-dir=/backup/full \
--incremental-dir=/backup/inc1
# 应用第二个增量(最后一个不需要--apply-log-only)
xtrabackup --prepare --target-dir=/backup/full \
--incremental-dir=/backup/inc2
# 3. 恢复数据(必须停止MySQL)
systemctl stop mysqld
# 备份原数据目录
mv /var/lib/mysql /var/lib/mysql_old
# 恢复数据
xtrabackup --copy-back --target-dir=/backup/full --datadir=/var/lib/mysql
# 或者使用move-back(会删除备份文件)
# xtrabackup --move-back --target-dir=/backup/full --datadir=/var/lib/mysql
# 4. 修改权限
chown -R mysql:mysql /var/lib/mysql
# 5. 启动MySQL
systemctl start mysqld
4.6 xtrabackup的优缺点
优点:
- 热备份,不锁表(InnoDB)
- 备份和恢复速度快
- 支持增量备份
- 适合大数据量
缺点:
- 学习成本较高
- 不能跨版本恢复
- 只能备份InnoDB/XtraDB(MyISAM会短暂锁表)
- 需要额外安装
五、主从复制
5.1 主从复制架构
┌─────────────┐ ┌─────────────┐
│ Master │◄───────►│ Slave │
│ (主库) │ binlog │ (从库) │
└─────────────┘ └─────────────┘
│ │
▼ ▼
写操作 读操作
5.2 主从复制的作用
| 作用 | 说明 |
|---|---|
| 数据备份 | 从库是实时的数据备份 |
| 读写分离 | 主库写,从库读,分担压力 |
| 高可用 | 主库故障时,从库可切换为主库 |
| 数据分析 | 在从库执行统计查询,不影响主库 |
5.3 搭建主从复制
步骤1:配置主库
ini
# my.cnf 主库配置
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW
binlog-row-image = FULL
expire_logs_days = 7
max_binlog_size = 500M
# 需要复制的数据库
binlog-do-db = mydb
# 或者排除某些数据库
# binlog-ignore-db = test
sql
-- 创建复制用户
CREATE USER 'repl'@'%' IDENTIFIED BY 'repl_password';
GRANT REPLICATION SLAVE ON *.* TO 'repl'@'%';
FLUSH PRIVILEGES;
-- 查看主库状态
SHOW MASTER STATUS;
-- 记录File和Position,如:mysql-bin.000001, 154
步骤2:备份主库并导入从库
bash
# 主库执行(锁表备份)
mysqldump -u root -p --single-transaction --master-data=2 mydb > mydb_backup.sql
# 将备份文件复制到从库并导入
mysql -u root -p mydb < mydb_backup.sql
步骤3:配置从库
ini
# my.cnf 从库配置
[mysqld]
server-id = 2
relay-log = mysql-relay-bin
read-only = 1
# 需要复制的数据库
replicate-do-db = mydb
sql
-- 配置主库信息
CHANGE MASTER TO
MASTER_HOST='master_host',
MASTER_USER='repl',
MASTER_PASSWORD='repl_password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
-- 启动复制
START SLAVE;
-- 查看从库状态
SHOW SLAVE STATUS\G
-- 检查:Slave_IO_Running: Yes
-- Slave_SQL_Running: Yes
5.4 读写分离
java
// Spring Boot读写分离配置示例
@Configuration
public class DataSourceConfig {
@Bean
public DataSource routingDataSource() {
DynamicRoutingDataSource routingDataSource = new DynamicRoutingDataSource();
Map<Object, Object> targetDataSources = new HashMap<>();
targetDataSources.put("master", masterDataSource());
targetDataSources.put("slave", slaveDataSource());
routingDataSource.setTargetDataSources(targetDataSources);
routingDataSource.setDefaultTargetDataSource(masterDataSource());
return routingDataSource;
}
}
// 使用注解切换数据源
@Service
public class UserService {
@Master // 走主库
public void updateUser(User user) {
userMapper.update(user);
}
@Slave // 走从库
public User getUser(Long id) {
return userMapper.selectById(id);
}
}
5.5 主从延迟问题
sql
-- 查看主从延迟
SHOW SLAVE STATUS\G
-- Seconds_Behind_Master: 0 表示无延迟
-- 原因:
-- 1. 从库性能差
-- 2. 大事务
-- 3. 网络延迟
-- 4. 从库有慢查询
-- 解决方案:
-- 1. 提升从库硬件
-- 2. 拆分大事务
-- 3. 使用并行复制(MySQL 5.7+)
-- 4. 避免在从库执行慢查询
六、数据恢复
6.1 全量恢复
bash
# 场景:整个数据库被删除
# 1. 停止MySQL(如果是物理备份)
systemctl stop mysqld
# 2. 清理数据目录(谨慎!)
mv /var/lib/mysql /var/lib/mysql_corrupted
mkdir /var/lib/mysql
# 3. 恢复数据
# 方式1:mysqldump恢复
mysql -u root -p < full_backup.sql
# 方式2:xtrabackup恢复
xtrabackup --copy-back --target-dir=/backup/full --datadir=/var/lib/mysql
chown -R mysql:mysql /var/lib/mysql
# 4. 启动MySQL
systemctl start mysqld
6.2 时间点恢复(PITR)
bash
# 场景:误删数据,需要恢复到某个时间点
# 1. 找到最近的全量备份并恢复
mysql -u root -p < full_backup_20240114_020000.sql
# 2. 找到需要恢复到的binlog位置或时间
# 查看binlog
mysqlbinlog /var/lib/mysql/mysql-bin.000005
# 3. 应用binlog到指定位置
mysqlbinlog --start-position=1234 --stop-position=5678 \
/var/lib/mysql/mysql-bin.000005 | mysql -u root -p
# 或者按时间恢复
mysqlbinlog --start-datetime="2024-01-15 10:00:00" \
--stop-datetime="2024-01-15 10:30:00" \
/var/lib/mysql/mysql-bin.000005 | mysql -u root -p
6.3 误删恢复
sql
-- 场景:DELETE FROM orders WHERE 1=1; (忘记加WHERE条件)
-- 方案1:从binlog恢复(需要binlog_format=ROW)
-- 使用mysqlbinlog提取DELETE语句,转换为INSERT
-- 方案2:从延迟从库恢复
-- 如果有延迟从库(延迟1小时),可以从中恢复数据
-- 方案3:从备份恢复 + binlog追平
-- 1. 恢复备份到临时库
-- 2. 用binlog追平到误删前一刻
-- 3. 导出被删数据,导入生产库
-- 方案4:使用闪回工具(binlog2sql)
# 安装binlog2sql
git clone https://github.com/danfengcao/binlog2sql.git
# 生成回滚SQL
python binlog2sql.py -h127.0.0.1 -P3306 -uadmin -p'admin' \
-d mydb -t orders --start-file='mysql-bin.000005' \
--start-datetime='2024-01-15 10:00:00' \
--stop-datetime='2024-01-15 10:30:00' -B > rollback.sql
# 执行回滚
mysql -u root -p < rollback.sql
七、实战:制定备份策略
7.1 备份策略设计原则
3-2-1备份原则:
- 3份数据副本
- 2种不同存储介质
- 1份异地备份
7.2 示例备份策略
场景:电商网站,数据量500GB,要求RPO<1小时,RTO<2小时
| 备份类型 | 频率 | 保留时间 | 工具 | 存储位置 |
|---|---|---|---|---|
| 全量备份 | 每周日02:00 | 4周 | xtrabackup | 本地NAS |
| 增量备份 | 每天02:00 | 7天 | xtrabackup | 本地NAS |
| binlog备份 | 实时 | 14天 | mysqlbinlog | 本地NAS |
| 全量备份 | 每周日03:00 | 12周 | xtrabackup | 异地OSS |
| 逻辑备份 | 每天04:00 | 30天 | mysqldump | 异地OSS |
7.3 自动化备份脚本
bash
#!/bin/bash
# backup.sh - MySQL自动备份脚本
# 配置
BACKUP_DIR="/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="backup"
DB_PASS="backup_password"
RETENTION_DAYS=7
# 创建备份目录
mkdir -p $BACKUP_DIR/{full,incremental,logs}
# 日志函数
log() {
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a $BACKUP_DIR/logs/backup.log
}
# 全量备份(周日执行)
full_backup() {
log "Starting full backup..."
xtrabackup --backup \
--target-dir=$BACKUP_DIR/full/$DATE \
--user=$DB_USER --password=$DB_PASS \
2>> $BACKUP_DIR/logs/backup.log
if [ $? -eq 0 ]; then
log "Full backup completed: $DATE"
# 压缩备份
tar czf $BACKUP_DIR/full/${DATE}.tar.gz -C $BACKUP_DIR/full $DATE
rm -rf $BACKUP_DIR/full/$DATE
# 上传到OSS
ossutil cp $BACKUP_DIR/full/${DATE}.tar.gz oss://mybucket/mysql/full/
else
log "Full backup FAILED!"
# 发送告警
curl -X POST "https://alert.example.com/send" \
-d "message=MySQL full backup failed"
fi
}
# 增量备份(每天执行)
incremental_backup() {
log "Starting incremental backup..."
# 找到最新的全量备份作为基础
BASE_DIR=$(ls -td $BACKUP_DIR/full/*/ | head -1)
xtrabackup --backup \
--target-dir=$BACKUP_DIR/incremental/$DATE \
--incremental-basedir=$BASE_DIR \
--user=$DB_USER --password=$DB_PASS \
2>> $BACKUP_DIR/logs/backup.log
if [ $? -eq 0 ]; then
log "Incremental backup completed: $DATE"
else
log "Incremental backup FAILED!"
fi
}
# 清理旧备份
cleanup() {
log "Cleaning up old backups..."
find $BACKUP_DIR/full -name "*.tar.gz" -mtime +$RETENTION_DAYS -delete
find $BACKUP_DIR/incremental -type d -mtime +$RETENTION_DAYS -exec rm -rf {} \;
}
# 主逻辑
DAY_OF_WEEK=$(date +%u)
if [ $DAY_OF_WEEK -eq 7 ]; then
full_backup
else
incremental_backup
fi
cleanup
log "Backup job completed."
7.4 备份验证
bash
#!/bin/bash
# verify_backup.sh - 备份验证脚本
BACKUP_FILE=$1
# 1. 检查文件是否存在且非空
if [ ! -s "$BACKUP_FILE" ]; then
echo "ERROR: Backup file is empty or does not exist"
exit 1
fi
# 2. 检查文件完整性(如果是压缩文件)
if [[ $BACKUP_FILE == *.gz ]]; then
gzip -t $BACKUP_FILE
if [ $? -ne 0 ]; then
echo "ERROR: Backup file is corrupted"
exit 1
fi
fi
# 3. 定期恢复测试(每周一次)
# 创建临时实例恢复数据并验证
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS test_restore;"
mysql -u root -p test_restore < $BACKUP_FILE
# 4. 检查表数量和数据量
TABLE_COUNT=$(mysql -u root -p -N -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema='test_restore';")
if [ $TABLE_COUNT -eq 0 ]; then
echo "ERROR: No tables found in backup"
exit 1
fi
echo "Backup verification PASSED"
八、踩坑提醒
8.1 备份文件要定期验证
bash
# 血泪教训:备份文件损坏,恢复时才发现
# 必须定期做恢复演练!
# 建议:每月至少一次全量恢复演练
# 验证备份完整性
gzip -t backup.sql.gz # 检查压缩文件
md5sum backup.sql.gz > backup.sql.gz.md5 # 生成校验和
md5sum -c backup.sql.gz.md5 # 验证校验和
8.2 binlog_expire_logs_days设置
ini
# my.cnf
[mysqld]
# 设置binlog保留天数(默认0,永不过期)
binlog_expire_logs_seconds = 604800 # 7天(MySQL 8.0)
# 或
expire_logs_days = 7 # MySQL 5.7
# 注意:
# 1. 不要设置太短,否则无法做时间点恢复
# 2. 也不要设置太长,会占用大量磁盘空间
# 3. 建议至少保留7-14天
8.3 备份时的锁问题
sql
-- 坑:mysqldump默认会锁表,影响业务
-- 解决方案1:使用--single-transaction(InnoDB)
mysqldump --single-transaction -u root -p mydb > backup.sql
-- 解决方案2:使用xtrabackup(热备)
xtrabackup --backup --target-dir=/backup
-- 解决方案3:从从库备份
-- 在主从架构中,从从库执行备份
8.4 大表备份的坑
bash
# 坑:单表过大,mysqldump备份超时
# 解决方案1:分片备份
mysqldump --where "id BETWEEN 1 AND 1000000" mydb big_table > part1.sql
mysqldump --where "id BETWEEN 1000001 AND 2000000" mydb big_table > part2.sql
# 解决方案2:使用xtrabackup
xtrabackup --backup --target-dir=/backup
# 解决方案3:使用mydumper(多线程备份)
mydumper -u root -p -B mydb -o /backup -t 4
8.5 恢复时的字符集问题
sql
-- 坑:备份和恢复的字符集不一致,导致乱码
-- 备份时指定字符集
mysqldump --default-character-set=utf8mb4 -u root -p mydb > backup.sql
-- 恢复时也指定字符集
mysql --default-character-set=utf8mb4 -u root -p mydb < backup.sql
-- 或者在SQL文件头部添加
SET NAMES utf8mb4;
九、面试高频考点
9.1 mysqldump和xtrabackup的区别?
答案:
| 对比项 | mysqldump | xtrabackup |
|---|---|---|
| 备份类型 | 逻辑备份 | 物理备份 |
| 备份速度 | 慢 | 快 |
| 恢复速度 | 慢 | 快 |
| 是否锁表 | 是(默认) | 否(InnoDB热备) |
| 增量备份 | 不支持 | 支持 |
| 跨版本 | 支持 | 不支持 |
| 适用场景 | 小数据量、跨版本 | 大数据量、快速恢复 |
9.2 主从延迟怎么解决?
答案:
- 硬件升级:提升从库配置
- 并行复制:开启slave_parallel_workers(MySQL 5.7+)
- 优化大事务:拆分大事务为小事务
- 减少从库压力:从库只用于复制,不跑查询
- 使用GTID:便于故障切换和延迟监控
- 网络优化:主从之间使用专线或同城部署
9.3 如何实现零数据丢失?
答案:
- 半同步复制:after_sync模式,保证至少一个从库收到binlog
- 组复制(MGR):多数派确认机制
- 双主架构:两个主库互相同步
- 异地多活:多个数据中心同时写入
- 定期备份 + binlog:最坏情况下恢复到最近时间点
9.4 误删数据如何恢复?
答案:
- 立即止损:停止写入,防止数据被覆盖
- 从备份恢复:恢复最近的全量备份
- binlog追平:使用mysqlbinlog恢复到误删前一刻
- 延迟从库:如果有延迟从库,直接切换
- 闪回工具:使用binlog2sql生成回滚SQL
9.5 如何设计备份策略?
答案:
- 3-2-1原则:3份副本、2种介质、1份异地
- 全量+增量:全量定期做,增量每天做
- binlog备份:实时备份,用于时间点恢复
- 定期演练:每月至少一次恢复演练
- 监控告警:备份失败立即通知
十、总结
今天我们学习了MySQL备份与恢复的完整知识体系:
核心知识点
- 备份的重要性:数据是生命线,备份是底线
- 备份类型 :
- 全量/增量/差异
- 逻辑备份/物理备份
- 热备/温备/冷备
- 备份工具 :
- mysqldump:简单、跨版本
- xtrabackup:快速、热备、支持增量
- 主从复制:数据备份、读写分离、高可用
- 数据恢复:全量恢复、时间点恢复、误删恢复
- 备份策略:3-2-1原则,定期验证
关键命令速查
bash
# mysqldump
mysqldump -u root -p --single-transaction mydb > backup.sql
# xtrabackup
xtrabackup --backup --target-dir=/backup
xtrabackup --prepare --target-dir=/backup
xtrabackup --copy-back --target-dir=/backup
# 恢复
mysql -u root -p < backup.sql
十一、下一步预告
Day15 - MySQL面试高频考点汇总
在最后一篇文章中,我们将:
- 汇总所有面试高频考点
- 按主题分类整理(基础、查询、索引、事务、锁、优化、架构)
- 高频SQL手写题详解
- 学习路线总结
这是整个系列的压轴大戏,将帮助你系统梳理MySQL知识体系,从容应对面试挑战!
参考资料
互动话题
- 你们公司的备份策略是怎样的?RPO和RTO是多少?
- 你遇到过数据丢失的情况吗?是如何恢复的?
- 对于备份,你还有什么好的实践经验或踩坑经历?
欢迎在评论区留言讨论,如果觉得文章有帮助,别忘了点赞收藏哦!我们下节课见!
本文是MySQL全面教学系列第14篇,系列文章持续更新中...