mysql物理迁移后启动失败,若日志报can't change dir to或unable to lock ./ibdata1且路径、权限、磁盘均正常,则大概率是网卡uuid变更导致systemd动态路径(如/run/mysqld)未正确创建或权限缺失,需检查tmpfiles.d规则、重建socket目录并验证归属与selinux上下文。

MySQL物理迁移后启动失败,如果错误日志里反复出现 Can't change dir to 或 InnoDB: Unable to lock ./ibdata1,但 datadir 路径、权限、磁盘空间都确认无误,那大概率是网卡 UUID 变更触发了 systemd 的路径访问限制——不是 MySQL 本身的问题,而是它运行时依赖的 /run/systemd/resolve/stub-resolv.conf 或 /run/systemd/netif/links/ 等动态生成路径因网卡重命名而失效。
为什么网卡 UUID 变更会导致 mysqld 启动失败
物理机迁移(尤其是克隆、P2V、云平台重部署)后,系统识别出新网卡,/sys/class/net/ 下设备名可能从 eth0 变为 ens33 或 enp0s3,进而导致 systemd-networkd 生成的 runtime 文件路径变化。MySQL 若在 my.cnf 中配置了 socket 指向 /run/mysqld/mysqld.sock,而该目录由 systemd 通过 tmpfiles.d 规则按网卡状态动态创建,旧规则就可能失效。
典型表现:
- systemctl start mysql 报错:
Job for mysql.service failed because the control process exited with error code. - journalctl -u mysql -n 50 显示:
Failed at step EXEC spawning /usr/sbin/mysqld: No such file or directory(实际文件存在),或提示 socket 目录不可写 - 手动执行
sudo -u mysql /usr/sbin/mysqld --defaults-file=/etc/my.cnf --console却能成功启动
检查并重建 systemd 对 MySQL socket 目录的管理
systemd 不是靠 mkdir 创建 socket 目录,而是读取 /usr/lib/tmpfiles.d/mysql.conf(或 /etc/tmpfiles.d/mysql.conf)里的规则。网卡变更后,若该文件中路径含 %i、%H 或依赖 networkd 的变量,就可能跳过创建。
实操建议:
- 运行
systemd-tmpfiles --prefix=/run --create强制触发所有/run下的 tmpfiles 规则执行 - 检查是否存在 MySQL 对应规则:
ls /usr/lib/tmpfiles.d/*mysql* /etc/tmpfiles.d/*mysql* 2>/dev/null;若无,手动创建/etc/tmpfiles.d/mysql.conf,内容为:d /run/mysqld 0755 mysql mysql -
- 确认目录已生成:
ls -ld /run/mysqld,输出应为drwxr-xr-x 2 mysql mysql - 重启 systemd 管理:
sudo systemctl daemon-reload
验证 my.cnf 中 socket 路径是否与 systemd 一致
MySQL 启动时会尝试创建 socket 文件,路径必须和 systemd 创建的目录匹配,且不能指向已被其他服务占用的路径(如 /tmp/mysql.sock 在某些发行版中被 systemd-resolved 占用)。
实操建议:
- 查当前生效的 socket 路径:
mysqld --verbose --help | grep "socket",或看my.cnf中[mysqld]段的socket值 - 确保该路径父目录就是上一步创建的
/run/mysqld,例如:socket = /run/mysqld/mysqld.sock - 避免使用
/tmp/下路径:部分系统对/tmp启用noexec或nodev挂载选项,导致 mysqld 无法写入 socket - 改完配置后不要直接
systemctl restart mysql,先sudo -u mysql touch /run/mysqld/test && sudo -u mysql rm /run/mysqld/test验证写权限
绕过 systemd 临时启动以确认问题根源
如果上述步骤仍失败,可跳过 systemd 尝试裸启,快速验证是否真是环境层问题而非 MySQL 自身损坏。
实操建议:
- 停服务:
sudo systemctl stop mysql - 清空残留锁:
sudo rm -f /run/mysqld/mysqld.pid /var/lock/subsys/mysqld - 手动启动并观察终端输出:
sudo -u mysql /usr/sbin/mysqld --defaults-file=/etc/my.cnf --user=mysql --console
- 若成功,说明问题确实在 systemd 单元或 tmpfiles 配置;此时可对比
systemctl cat mysql输出,检查ExecStart=是否硬编码了旧路径,或是否漏掉了RuntimeDirectory=mysqld这类关键指令
真正麻烦的不是 socket 目录不存在,而是它存在但 systemd 没给 mysql 用户写权限——因为目录归属仍是 root,或者 SELinux 上下文没更新。这类细节在物理迁移后极易被忽略,但只差一条 chown 或 chcon 就卡住整个启动流程。











