先说个血泪教训:备份了不等于能恢复。
我见过有人备份脚本跑了一年,真出事了发现备份文件全是空的——脚本报错没人看。
所以备份这事,分两步:怎么备和怎么验。
备份的几个层次
从简单到复杂,看你的数据值多少钱。
最基础:mysqldump定时导出
#!/bin/bash
DATE=$(date +%Y%m%d_%H%M%S)
mysqldump -u backup -p'password' \
--all-databases \
--single-transaction \
--routines --triggers --events \
| gzip > /data/backup/all_db_$DATE.sql.gz
# 删除7天前的备份
find /data/backup -name "*.sql.gz" -mtime +7 -delete
扔到crontab里,每天凌晨跑一次:
0 3 * * * /path/to/backup.sh >> /var/log/backup.log 2>&1
这个方案的问题:备份只在本地,服务器挂了或者机房出事,备份也没了。
进阶:备份传到云存储
本地备份完,传一份到云上:
# 阿里云OSS
ossutil cp /data/backup/all_db_$DATE.sql.gz oss://your-bucket/mysql/
# 或者AWS S3
aws s3 cp /data/backup/all_db_$DATE.sql.gz s3://your-bucket/mysql/
云存储很便宜,几十G也就几块钱一个月。
再进阶:binlog实时备份
mysqldump是某个时间点的快照。如果早上3点备份,下午2点数据库挂了,这中间11小时的数据就丢了。
想要更精确的恢复,要备份binlog:
# 开启binlog(my.cnf)
[mysqld]
log-bin = mysql-bin
binlog_format = ROW
expire_logs_days = 7
# 实时拉取binlog到备份服务器
mysqlbinlog --read-from-remote-server \
--host=主库IP \
--raw --stop-never \
--result-file=/data/binlog/ \
mysql-bin.000001
恢复的时候,先恢复全量备份,再把binlog应用到指定时间点:
mysql < full_backup.sql
mysqlbinlog --stop-datetime="2024-01-15 14:30:00" binlog.* | mysql
这样就能恢复到下午2点30分那一刻的状态。
异地备份:真正的保险
上面说的都是本地+云存储。但如果你的云账号被黑了呢?或者云厂商出问题呢?
3-2-1原则:3份数据、2种介质、1份异地。
我自己的做法是在家里放了台NAS,跑一个MySQL从库,实时同步公司服务器的数据。
问题是:家里没有公网IP,公司服务器怎么连到家里的NAS?
我用的是组网方案,把公司服务器和家里NAS组成虚拟局域网。配置好之后,MySQL主从复制就像在同一个内网:
-- 家里NAS上的MySQL配置
CHANGE MASTER TO
MASTER_HOST = '10.26.0.1', -- 组网的内网IP
MASTER_USER = 'repl',
MASTER_PASSWORD = 'xxx',
MASTER_LOG_FILE = 'mysql-bin.000001',
MASTER_LOG_POS = 154;
START SLAVE;
这样即使公司服务器和云存储同时出问题,家里还有一份实时同步的数据。
我用的星空组网,配置比自己搭frp简单。当然你要是有公网IP的云服务器,自己搭也行。
备份验证:最容易忽略的一步
备份了不验证,等于没备份。
定期做恢复测试:
# 下载最新备份
ossutil cp oss://bucket/mysql/latest.sql.gz /tmp/
# 解压
gunzip /tmp/latest.sql.gz
# 恢复到测试库
mysql -h test-server -u root -p test_db < /tmp/latest.sql
# 验证:查几个关键表的数据量
mysql -e "SELECT COUNT(*) FROM test_db.users;"
mysql -e "SELECT COUNT(*) FROM test_db.orders;"
建议每月至少做一次恢复测试。
检查备份文件完整性:
# 检查gzip文件是否损坏
gunzip -t backup.sql.gz
# 检查SQL文件结尾是否正常
tail -5 backup.sql
# 正常应该有:-- Dump completed on 2024-01-15 03:00:01
我之前就遇到过备份脚本因为磁盘满了,导出到一半就停了,文件看着有,其实是残的。
云数据库的备份
如果用的是阿里云RDS、腾讯云这些,它们自带备份功能,省心但要花钱。
优点:
- 自动备份,不用操心
- 跨地域备份一键开启
- 恢复方便,控制台点点就行
缺点:
- 要花钱
- 数据在别人手里
- 被厂商绑定
我的建议是:云数据库的自动备份开着,但自己也拉一份到本地或者其他地方。鸡蛋不要放一个篮子里。
我的备份策略
分享一下我实际在用的:
每天凌晨3点:mysqldump全量备份
↓
上传阿里云OSS,保留30天
↓
家里NAS跑MySQL从库,通过组网实时同步
↓
binlog也同步到NAS
出事了怎么恢复:
- 误删数据 → 从OSS下载最近的全量 + binlog恢复到指定时间点
- 服务器挂了 → 切到家里的从库顶一下
- 云厂商跑路 → 还有家里的完整备份
成本:OSS一个月几块钱 + 家里本来就有的NAS。心里踏实。
最后
备份这事,没出事的时候觉得是成本,出事了才知道是救命的。
几个原则:
- 本地备份 + 云存储 + 异地,至少两个
- 定期验证,每月恢复测试一次
- 监控告警,备份失败要能第一时间知道
- binlog如果数据重要,考虑实时备份
宁可备份用不上,不能用的时候没有。
