必须停库或锁表才能用rsync同步mysql数据文件,否则因innodb持续写入导致备份不一致;需排除socket、pid文件并确保目标机用户权限一致;推荐mysqldump+rsync组合方案。

rsync 同步 MySQL 数据文件前必须停库或锁表
MySQL 的数据文件(如 ibdata1、ib_logfile0、表空间文件)在运行时被 InnoDB 持续写入,直接 rsync 会大概率产生不一致备份——恢复后可能报错 Tablespace is missing for table 或启动失败。
正确做法只有两种:
- 停掉 MySQL 服务后再
rsync整个/var/lib/mysql/目录(适合维护窗口期) - 运行中则必须先执行
FLUSH TABLES WITH READ LOCK+SHOW MASTER STATUS记下 binlog 位置,再rsync,最后UNLOCK TABLES(注意:该锁会阻塞所有写入,且不能在有活跃事务时安全执行)
不要直接 rsync /var/lib/mysql —— 权限和 socket 文件会出问题
rsync -av /var/lib/mysql/ user@remote:/backup/mysql/ 看似简单,但实际会带过去 mysql.sock、mysqld.pid 这类运行时文件,目标机若未停库,可能干扰新实例启动;更关键的是文件属主属组(通常是 mysql:mysql)在异地机器上未必存在,导致恢复后 MySQL 拒绝启动,报错 Can't start server: Bind on TCP/IP port 或权限拒绝。
实操建议:
- 同步前先
rsync -av --exclude='mysql.sock' --exclude='mysqld.pid' --exclude='*.pid' /var/lib/mysql/ ... - 目标机恢复前确保创建
mysql用户组,并用chown -R mysql:mysql /backup/mysql/ - 避免用 root 身份同步,改用
sudo -u mysql rsync ...保持上下文一致
用 mysqldump + rsync 组合才是生产常用方案
直接同步数据文件风险高、恢复步骤繁琐;而纯 mysqldump 又慢、大库容易超时。折中方案是:本地导出逻辑备份 + rsync 传到异地 + 远程导入。这样既规避了文件级一致性问题,又比全量物理同步更可控。
典型流程:
- 本地执行:
mysqldump --single-transaction --routines --triggers --databases db1 db2 > /backup/full_$(date +%F).sql - 压缩传输:
gzip /backup/full_*.sql && rsync /backup/full_*.sql.gz user@remote:/backup/ - 远程导入前确认字符集:
mysql --default-character-set=utf8mb4
注意:--single-transaction 对 MyISAM 表无效,若混用引擎,仍需锁表或停库。
rsync 增量同步 binlog 日志要配好 expire_logs_days
如果想靠 rsync 每小时拉一次新 binlog 实现近实时恢复,得先确保源库没自动清理旧日志:expire_logs_days 至少设为 7(默认是 0,即永不过期但磁盘满会删),否则 rsync 找不到前序日志,mysqlbinlog --start-position 就断链。
操作要点:
- 查当前设置:
SHOW VARIABLES LIKE 'expire_logs_days'; - 临时生效:
SET GLOBAL expire_logs_days = 7;(重启失效) - 永久生效:在
/etc/my.cnf的[mysqld]下加expire_logs_days = 7 - 同步命令建议加
--ignore-existing避免重复覆盖已传过的mysql-bin.000001等文件
binlog 是追加写,但文件名滚动后旧文件可能被 PURGE BINARY LOGS 清掉——这个动作不会通知 rsync,得靠监控或定期校验文件列表。










