3. MySQL逻辑备份:mysqldump实战
聊到MySQL备份,很多人第一反应就是mysqldump。说实话,这个工具我用了十几年,从MySQL 5.1一直跟到8.0,踩过的坑能写满一本小册子。今天咱们就把它彻底讲透。
3.1 什么是逻辑备份?
逻辑备份,说白了就是把数据库里的数据“翻译”成SQL语句。你想想看,一张表里的每一行数据,最终都会变成一条INSERT语句。恢复的时候,MySQL重新执行这些SQL,数据就回来了。
我遇到过不少新手问:“为什么不直接拷贝数据文件?”嗯,物理备份确实快,但跨版本、跨平台恢复时,逻辑备份的优势就出来了。你从MySQL 5.7迁移到8.0,mysqldump出来的SQL基本都能用。
3.2 单库备份实战
先来个最简单的。备份一个库,命令长这样:
mysqldump -u root -p --databases mydb > mydb_backup.sql
这里有个细节——--databases参数。加了这个,生成的SQL里会包含CREATE DATABASE和USE语句。恢复时直接跑就行,不用手动建库。
我个人习惯这样写:
mysqldump -u root -p --single-transaction --routines --triggers --events mydb > mydb_full.sql
--routines、--triggers、--events这三个参数,分别备份存储过程、触发器、事件。很多人在生产环境忘了加,恢复时才发现业务逻辑丢了。我曾经就因为这个,半夜被叫起来救火……
3.3 多库与全库备份
多库备份很简单,库名用空格隔开:
mysqldump -u root -p --databases db1 db2 db3 > multi_db.sql
全库备份呢?用--all-databases:
mysqldump -u root -p --all-databases > all_db.sql
但注意了,全库备份会包含mysql、sys这些系统库。恢复时如果覆盖了系统表,可能会出问题。我建议生产环境只备份业务库,系统库单独处理。
3.4 核心参数优化
这里有两个参数,是mysqldump的灵魂。不夸张地说,用对了保平安,用错了出大事。
3.4.1 --single-transaction
这个参数的作用,是让mysqldump在InnoDB引擎下获得一致性快照。什么意思呢?就是备份开始时,它开启一个事务,读取那个时间点的数据。备份过程中,其他事务的修改不会影响备份结果。
我建议:只要表是InnoDB,就一定要加这个参数。不加的话,mysqldump会对表加锁,业务写入会被阻塞。想象一下,凌晨2点跑备份,结果用户下单全卡住了……
核心原则:InnoDB表用--single-transaction,MyISAM表用--lock-tables。但说实话,现在谁还用MyISAM?
3.4.2 --master-data
这个参数有两个值:
| 值 | 作用 |
|---|---|
| --master-data=1 | 在备份文件中输出CHANGE MASTER TO语句,且不注释 |
| --master-data=2 | 同样输出CHANGE MASTER TO,但被注释掉了 |
我个人习惯用--master-data=2。为什么呢?因为备份文件里记录了主库的binlog位置,恢复时如果需要搭建从库,直接找到这行取消注释就能用。平时恢复数据,注释掉也不影响。
举个例子,备份文件里会看到这样的内容:
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000123', MASTER_LOG_POS=456789;
搭建从库时,把这行取消注释,再执行START SLAVE,数据就同步上了。
3.5 一致性备份原理
为什么说--single-transaction能保证一致性?这里得聊聊InnoDB的MVCC机制。
MVCC,全称多版本并发控制。简单理解:每行数据可能有多个版本,不同事务看到的是不同版本。mysqldump开启事务时,会得到一个事务ID,之后读取的数据都是这个ID对应的版本。
举个例子:
- mysqldump开始备份,事务ID=100
- 备份表A时,读到ID=100这个版本的数据
- 此时另一个事务修改了表A的一行数据,提交后ID=101
- mysqldump继续备份,仍然读ID=100的版本
这样,整个备份文件里的数据,都是同一个时间点的状态。这就是一致性备份。
小提示:如果表里有MyISAM引擎,--single-transaction就失效了。MyISAM不支持事务,只能全表锁。所以混合引擎的库,备份时要格外小心。
3.6 实战:一个完整的备份脚本
下面是我常用的备份脚本,你可以直接拿去用:
#!/bin/bash
# 数据库备份脚本
# 作者:资深工程师的日常
BACKUP_DIR="/data/backup/mysql"
DATE=$(date +%Y%m%d_%H%M%S)
DB_USER="root"
DB_PASS="your_password"
DB_NAME="mydb"
# 创建备份目录
mkdir -p $BACKUP_DIR/$DATE
# 执行备份
mysqldump -u$DB_USER -p$DB_PASS \
--single-transaction \
--master-data=2 \
--routines \
--triggers \
--events \
--flush-logs \
$DB_NAME | gzip > $BACKUP_DIR/$DATE/${DB_NAME}_${DATE}.sql.gz
# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功: $DATE"
else
echo "备份失败: $DATE"
fi
# 删除7天前的备份
find $BACKUP_DIR -type d -mtime +7 -exec rm -rf {} \;
这个脚本做了几件事:
- 每天生成一个带时间戳的备份文件
- 用gzip压缩,节省磁盘空间
- 自动清理7天前的旧备份
- 记录备份结果,方便监控
避坑指南:我曾经在生产环境直接跑mysqldump,结果磁盘写满了。从那以后,我每次备份前都会检查磁盘空间:df -h。另外,备份文件最好异地存储,别跟数据库放在同一台机器上。
3.7 知识体系总览
下面这张图,把mysqldump的核心知识点串起来了:
这张图把mysqldump的五个核心维度都列出来了。备份类型、核心参数、一致性原理、实战要点、避坑指南,每个环节都环环相扣。你照着这个体系去实践,基本不会出大问题。
好了,这一章的内容就到这儿。mysqldump虽然基础,但用好它需要理解背后的原理。下一章咱们聊聊物理备份,那又是另一番天地了。
公众号:蓝海资料掘金营,微信deep3321