MySQL数据目录迁移必须停服务后整体移动再软链,不可直接挪文件或仅链单库;datadir配置须保持原路径,迁移后需修复权限、SELinux上下文并验证表结构。

MySQL 数据目录迁移前必须停服务
不关 mysqld 直接挪文件,ibdata1 和 ib_logfile* 会被写坏,重启直接报错 Tablespace is missing for table 或卡在 recovery 阶段。软链接只是路径映射,底层文件 IO 还是走原设备,IO 路径一乱就丢数据。
- 确认当前数据路径:
SELECT @@datadir; - 用
systemctl stop mysql(或service mysqld stop)彻底停止进程,检查ps aux | grep mysql确保无残留 - 别用
KILL -9强杀,可能中断页刷盘
软链接只能挂载整个 datadir,不能只链单个库
MySQL 启动时会扫描 datadir 下所有子目录作为 database,如果只对 /var/lib/mysql/mydb 做软链,而 /var/lib/mysql 本身还是旧路径,那么新位置的表空间文件(.ibd)和数据字典不匹配,SHOW TABLES 会漏表,甚至 DROP DATABASE 误删物理文件。
- 正确做法:把整个
/var/lib/mysql移到新位置(如/data/mysql),再从原路径创建指向它的软链:ln -sf /data/mysql /var/lib/mysql -
my.cnf中的datadir必须保持原值(如/var/lib/mysql),不能改成新路径——否则软链失效,MySQL 会自己初始化一套空实例 - InnoDB 表的
.frm和.ibd必须在同一个挂载点下,跨文件系统软链会导致ALTER TABLE ... ENGINE=InnoDB失败
迁移后启动失败常见原因和查法
最常卡在权限、SELinux 和 socket 路径不一致上。MySQL 以 mysql 用户运行,但新目录往往属主是 root;CentOS/RHEL 默认开启 SELinux,会拦住 mysqld 访问非标准路径。
- 检查错误日志开头几行:
tail -20 /var/log/mysqld.log,重点看Can't open the mysql.plugin table(权限错)或Permission denied(SELinux) - 修复权限:
chown -R mysql:mysql /data/mysql,别漏mysql.sock对应目录(通常是/var/lib/mysql的父级) - 临时关 SELinux 测试:
setenforce 0;若恢复正常,需打策略:semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?",再restorecon -Rv /data/mysql
软链接方案不适合在线扩缩容或高可用场景
它只是路径重定向,没解决 I/O 瓶颈或单点故障。比如把 datadir 软链到 NFS,MySQL 会因 NFS 的锁机制和延迟直接 hang 死;主从复制中,如果从库用软链指向本地 SSD,但主库 binlog 在另一块盘,relay-log 路径没同步调整,START SLAVE 就会报 Failed to open the relay log。
- 生产环境更稳妥的做法:用
xtrabackup全量备份 + 恢复到新路径,再切 DNS 或 VIP - 若真要用软链,确保目标路径和原路径在同一台机器、同一文件系统类型(ext4/xfs)、且不跨网络存储
- 迁移后务必跑一次
mysqlcheck --all-databases --check-upgrade,验证表结构兼容性
chown、多一个 SELinux 上下文,就进不了 recovery。动手前先 ls -lZ /var/lib/mysql 和 ls -lZ /data/mysql 对比两遍。


















