离线迁移innodb表空间必须先停库。因缓冲池未刷盘、redo日志未同步,运行时直接复制.ibd等文件不可靠;仅flush tables with read lock无效,需systemctl stop mysqld并确认进程已终止,再复制.ibd、ibdata1、ib_logfile*及db.opt等全部关键文件,并严格校验属主(chown mysql:mysql)、selinux上下文及版本兼容性。

离线迁移表空间前必须停库
MySQL的InnoDB表空间(ibdata1、ib_logfile*、每个表的.ibd文件)不能在服务运行时直接复制用于可靠备份。哪怕只读,也可能因缓冲池未刷盘、redo日志未同步导致恢复失败。所以第一步永远是:先执行systemctl stop mysqld(或对应服务名),确认ps aux | grep mysqld无进程残留。
常见错误是只用FLUSH TABLES WITH READ LOCK就去拷文件——这对InnoDB无效,锁表不等于冻结事务状态,.ibd仍可能处于半写状态。
只复制业务表的.ibd文件是否可行?
可以,但有严格前提:该表必须启用innodb_file_per_table=ON(MySQL 5.6+默认开启),且从未执行过ALTER TABLE ... ENGINE=InnoDB等隐式重建操作(否则可能回退到共享表空间)。验证方式:SELECT TABLE_NAME, TABLE_SCHEMA FROM INFORMATION_SCHEMA.TABLES WHERE ENGINE='InnoDB' AND TABLE_SCHEMA NOT IN ('mysql','sys','performance_schema'); 然后检查对应.ibd文件是否存在且大小合理。
操作要点:
- 停库后,进入数据目录(如
/var/lib/mysql/db_name/),只复制*.ibd和db.opt -
ibdata1和ib_logfile*必须一并复制,否则无法启动——它们包含数据字典、undo日志等全局元数据 - 目标机恢复时,需先创建空库,再
CREATE TABLE结构(用SHOW CREATE TABLE导出),最后DISCARD TABLESPACE+ 替换.ibd+IMPORT TABLESPACE
mysqldump和物理复制哪个更快?
物理复制快得多,尤其对大库(>50GB)。mysqldump要逐行生成SQL、序列化、字符转义,IO和CPU压力都高;而cp -a或rsync -a只是块级拷贝,速度取决于磁盘带宽。但物理备份的代价是:只能恢复到同版本、同架构(x86/ARM)、同innodb_page_size的MySQL实例上。跨版本恢复大概率报错Tablespace mismatch或Unknown table engine 'InnoDB'。
如果你的离线环境里MySQL版本不固定,或者要迁到云厂商托管实例(如阿里云RDS),优先选mysqldump --single-transaction --routines --triggers,别碰.ibd。
恢复时权限和文件属主最容易被忽略
复制完文件后,直接systemctl start mysqld大概率失败,错误日志里常出现Operating system error number 13 in a file operation或Cannot open table。根本原因是:MySQL进程以mysql用户运行,但新复制的文件属主可能是root。必须执行chown -R mysql:mysql /var/lib/mysql/,且确保datadir目录权限为750。
另一个坑是SELinux:如果系统启用了SELinux,restorecon -Rv /var/lib/mysql比单纯改权限更稳妥。离线环境往往跳过这步,结果服务起来但数据库不可见。











