冷备份必须停掉mysqld而非仅kill连接,因为innodb需完整关闭流程(刷脏页、写checkpoint、关文件句柄)才能保证ibdata1、ib_logfile*和.ibd文件状态一致;否则恢复时必报innodb崩溃或表缺失错误。

mysqld 必须完全停止,否则拷贝出的 ibdata1、ib_logfile0 和 .ibd 文件必然不一致,恢复后启动直接失败。
为什么冷备份迁移必须停掉 mysqld 而不是只 kill 连接
InnoDB 在运行时持续刷脏页、写重做日志、更新元数据。哪怕只差一次 fsync,ib_logfile* 和 ibdata1 就可能处于中间态。你看到的 ps aux | grep mysqld 有进程,不代表它已安全落盘——只有 mysqladmin -uroot -p shutdown 或 systemctl stop mysqld 才会触发完整关闭流程:刷清 buffer pool、写 checkpoint、关闭文件句柄。
常见错误现象包括:
- 目标机启动时报
InnoDB: Database page corruption on disk -
SHOW DATABASES只返回mysql、sys,业务库消失 - 错误日志反复出现
Cannot open table mysql/user
rsync 同步时必须加的参数和路径写法
别用 rsync -avz /var/lib/mysql user@newhost:/var/lib/mysql——这会把源目录内容“铺平”到目标目录下,覆盖 auto.cnf 导致 server-uuid 冲突,主从直接断裂。
正确做法是保持层级结构:
- 源端执行:
rsync -avz --delete /var/lib/mysql/ user@newhost:/var/lib/mysql/(注意两个路径末尾都有/) - 目标端必须立刻执行:
chown -R mysql:mysql /var/lib/mysql - 若 SELinux 开启,补一句:
restorecon -Rv /var/lib/mysql
恢复前必须手动清理的三个关键文件
冷备份包不能直接扔进新实例启动。以下三项漏一项,mysqld 就起不来:
-
ib_logfile0和ib_logfile1:必须删除。InnoDB 启动时校验日志序列号,残留旧日志会拒绝启动 -
auto.cnf:如果目标机已有 MySQL 实例,保留该文件会导致server-uuid重复;建议备份时就--exclude=auto.cnf,或恢复后替换为新生成的 -
mysql.sock文件:虽然不在datadir下,但若旧 socket 文件残留且权限不对,mysqld可能因无法创建新 socket 而静默退出
版本和配置项不匹配的硬性限制
MySQL 5.7 的物理文件格式与 8.0 不兼容,ibdata1 无法被对方读取。哪怕 minor 版本差一点(如 5.7.28 → 5.7.33),也可能因页格式微调导致启动失败。
检查项必须逐条确认:
- 源和目标执行
mysqld --version,输出必须完全一致 - 目标机
my.cnf中[mysqld]段必须显式声明datadir = /var/lib/mysql,且路径末尾不能带斜杠 - 若源库开启
innodb_encrypt_tables=ON,密钥未导出则目标机解密失败,且错误日志里几乎不报明文提示
真正麻烦的不是拷贝本身,而是 datadir 路径、server-uuid、ib_logfile 三者之间的隐式耦合——它们不报错,只静默拒绝启动。











