如何通过rsync同步实现MySQL数据库跨地域的灾备备份?
- 内容介绍
- 文章标签
- 相关推荐
本文共计964个文字,预计阅读时间需要4分钟。
直接使用 rsync 命令同步 MySQL 的 /var/lib/mysql 目录时,若出现失败,通常是 InnoDB 表空间处于活跃状态,文件内容不一致。恢复后,大约有 50% 的几率报错 Tablespace is missing for table... 或启动失败。只有 MySQL 完全停止时才可能成功,但生产环境无法接受停机。
正确做法是先生成逻辑备份文件:
-
mysqldump --single-transaction --routines --triggers --databases db1 db2 > /backup/full_$(date +\%Y\%m\%d).sql(适合中小库,--single-transaction保证一致性) - 大库(>50GB)建议用
mysqlpump(支持并行导出)或mydumper(需额外安装),避免单线程卡死 - 备份前加
FLUSH LOGS(可选),便于后续 binlog 恢复定位起点
rsync 同步备份文件时必须加 --delete 和 --checksum
只用 rsync -avz 同步会导致异地备份目录不断膨胀:旧的 .sql 文件不会被清理,磁盘迟早占满;且默认按修改时间+大小判断是否跳过,若因网络中断导致文件写半截、大小未变但内容损坏,rsync 就会跳过,灾备失效。
安全同步命令示例:
rsync -avz --delete --checksum --progress \ /backup/full_*.sql \ user@backup-server:/backup/mysql/
-
--delete确保目标端只保留本次同步的备份文件,自动清理过期备份(配合定时脚本删除本地旧文件更稳妥) -
--checksum强制逐块校验内容,哪怕时间/大小一致也重传,防静默损坏 - 务必用
ssh key免密登录,并限制 backup-server 上的rsync账户权限(如仅允许rsync --server,禁用 shell)
异地恢复不能只靠 rsync 文件,必须验证 mysql 可导入
很多团队把 rsync 成功当成“灾备就绪”,结果真出事才发现:mysqldump 导出时用了 --set-gtid-purged=ON,但目标 MySQL 未开启 GTID;或者导出文件里含 CREATE DATABASE,但目标实例已存在同名库且字符集不一致,source 报错退出。
恢复前必须做最小化验证:
- 在测试机上执行
mysql -u root -e "CREATE DATABASE IF NOT EXISTS test_restore DEFAULT CHARACTER SET utf8mb4;" - 然后
mysql -u root test_restore ,观察是否报错(尤其关注 <code>ERROR 1046、ERROR 1273、ERROR 1050) - 导入后运行
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'test_restore';,确认表数非零 - 关键业务表抽样查几条数据,排除空表或乱码
真正可用的异地灾备需要补上 binlog 增量同步
纯 mysqldump + rsync 是“最终一致性”方案,两次备份之间产生的数据变更完全丢失。如果 RPO(恢复点目标)要求小于 5 分钟,必须叠加 binlog:
- 主库开启
log-bin,设置expire_logs_days = 7(防止磁盘爆) - 用
rsync每 5 分钟同步/var/lib/mysql/mysql-bin.*到异地(注意:不要同步正在写的mysql-bin.index,改用SHOW BINARY LOGS获取最新文件名) - 灾备恢复流程变成:先恢复最近一次全量
.sql,再按mysqlbinlog解析并重放其后所有 binlog
这一步容易被跳过,但没它,所谓“异地灾备”其实只是“异地存档”。
本文共计964个文字,预计阅读时间需要4分钟。
直接使用 rsync 命令同步 MySQL 的 /var/lib/mysql 目录时,若出现失败,通常是 InnoDB 表空间处于活跃状态,文件内容不一致。恢复后,大约有 50% 的几率报错 Tablespace is missing for table... 或启动失败。只有 MySQL 完全停止时才可能成功,但生产环境无法接受停机。
正确做法是先生成逻辑备份文件:
-
mysqldump --single-transaction --routines --triggers --databases db1 db2 > /backup/full_$(date +\%Y\%m\%d).sql(适合中小库,--single-transaction保证一致性) - 大库(>50GB)建议用
mysqlpump(支持并行导出)或mydumper(需额外安装),避免单线程卡死 - 备份前加
FLUSH LOGS(可选),便于后续 binlog 恢复定位起点
rsync 同步备份文件时必须加 --delete 和 --checksum
只用 rsync -avz 同步会导致异地备份目录不断膨胀:旧的 .sql 文件不会被清理,磁盘迟早占满;且默认按修改时间+大小判断是否跳过,若因网络中断导致文件写半截、大小未变但内容损坏,rsync 就会跳过,灾备失效。
安全同步命令示例:
rsync -avz --delete --checksum --progress \ /backup/full_*.sql \ user@backup-server:/backup/mysql/
-
--delete确保目标端只保留本次同步的备份文件,自动清理过期备份(配合定时脚本删除本地旧文件更稳妥) -
--checksum强制逐块校验内容,哪怕时间/大小一致也重传,防静默损坏 - 务必用
ssh key免密登录,并限制 backup-server 上的rsync账户权限(如仅允许rsync --server,禁用 shell)
异地恢复不能只靠 rsync 文件,必须验证 mysql 可导入
很多团队把 rsync 成功当成“灾备就绪”,结果真出事才发现:mysqldump 导出时用了 --set-gtid-purged=ON,但目标 MySQL 未开启 GTID;或者导出文件里含 CREATE DATABASE,但目标实例已存在同名库且字符集不一致,source 报错退出。
恢复前必须做最小化验证:
- 在测试机上执行
mysql -u root -e "CREATE DATABASE IF NOT EXISTS test_restore DEFAULT CHARACTER SET utf8mb4;" - 然后
mysql -u root test_restore ,观察是否报错(尤其关注 <code>ERROR 1046、ERROR 1273、ERROR 1050) - 导入后运行
SELECT COUNT(*) FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'test_restore';,确认表数非零 - 关键业务表抽样查几条数据,排除空表或乱码
真正可用的异地灾备需要补上 binlog 增量同步
纯 mysqldump + rsync 是“最终一致性”方案,两次备份之间产生的数据变更完全丢失。如果 RPO(恢复点目标)要求小于 5 分钟,必须叠加 binlog:
- 主库开启
log-bin,设置expire_logs_days = 7(防止磁盘爆) - 用
rsync每 5 分钟同步/var/lib/mysql/mysql-bin.*到异地(注意:不要同步正在写的mysql-bin.index,改用SHOW BINARY LOGS获取最新文件名) - 灾备恢复流程变成:先恢复最近一次全量
.sql,再按mysqlbinlog解析并重放其后所有 binlog
这一步容易被跳过,但没它,所谓“异地灾备”其实只是“异地存档”。

