mysql启动失败主因是权限与selinux限制,需正确赋权、配置selinux上下文、同步修改my.cnf及systemd服务参数,并仅复制数据库子目录而非innodb系统文件,最后交叉验证datadir真实路径。

MySQL 启动失败报错 Can't find file: './mysql/plugin.frm' 或数据目录无权限
这是改存储目录后最常遇到的两个现象,本质是 MySQL 进程无法读写新路径——不是配置写错了,而是系统层面没放行。Linux 下 MySQL 默认以 mysql 用户运行,它对目标目录必须有 rwx 权限,且 SELinux(若启用)会拦截非标准路径访问。
实操建议:
- 确认目标挂载点已正确挂载且不为
noexec、nosuid或nodev选项(检查/proc/mounts或用mount | grep /data) - 用
chown -R mysql:mysql /data/mysql赋权,别只改目录不改里面文件 - CentOS/RHEL 7+ 默认开启 SELinux,需运行
semanage fcontext -a -t mysqld_db_t "/data/mysql(/.*)?"再执行restorecon -Rv /data/mysql - 不要用
chmod 777临时绕过,MySQL 会拒绝启动(日志里明确提示World-writable config file is insecure)
修改 datadir 的三个关键位置:配置、服务、初始化目录结构
只改 my.cnf 里的 datadir 不够,MySQL 启动时还会校验 socket、pid 文件路径和实际数据文件一致性。漏掉任一环节都会卡在启动阶段。
实操建议:
- 编辑
/etc/my.cnf,在[mysqld]段落下设置datadir=/data/mysql,同时显式指定socket=/data/mysql/mysql.sock和pid-file=/data/mysql/mysqld.pid - 检查 systemd 服务文件是否硬编码了旧路径:运行
systemctl cat mysqld,若看到Environment="MYSQLD_OPTS=--datadir=/var/lib/mysql"类似内容,需覆盖该变量或重写服务文件 - 移动数据前先停库:
systemctl stop mysqld;移动后用mysql_install_db --user=mysql --datadir=/data/mysql(5.7 及以前)或mysqld --initialize --user=mysql --datadir=/data/mysql(8.0+)补全缺失的系统表结构
从 /var/lib/mysql 迁移数据时,ibdata1 和 ib_logfile* 不能直接复制
这些是 InnoDB 共享表空间和重做日志文件,它们的路径、大小、checksum 都和初始化时的 datadir 绑定。强行复制过去会导致 MySQL 启动时反复报 InnoDB: Database page corruption on disk 或直接崩溃。
实操建议:
- 停库后只复制数据库子目录(如
mysql/、performance_schema/、你的业务库名目录),以及mysql-bin.*、mysql-relay-bin.*等二进制日志(如果需要保留主从) -
ibdata1、ib_logfile0、ib_logfile1全部删除,让 MySQL 启动时按配置重新生成(确保innodb_data_file_path和innodb_log_file_size在 my.cnf 中已设好) - 若原库启用了
innodb_file_per_table=ON,每个.ibd文件可单独复制,但复制前务必确认对应表在information_schema.INNODB_SYS_TABLES中存在且状态正常
验证新 datadir 是否真正生效:别只信 SELECT @@datadir
SELECT @@datadir 返回的是配置值,不是运行时真实路径。MySQL 可能因权限/SELinux/路径不存在等问题静默回退到编译默认路径(如 /var/lib/mysql),而进程仍在跑,你却以为改成功了。
实操建议:
- 连接后立刻执行
SHOW VARIABLES LIKE 'datadir';和SELECT FILE_PATH FROM performance_schema.data_locks LIMIT 1;(8.0+)交叉验证 - 查进程打开的文件:
lsof -i :3306 | grep mysql找到 mysqld 进程号,再运行lsof -p <pid> | grep mysql | head -5</pid>,看实际加载的 .frm/.ibd 文件是否来自新路径 - 往新库建一张测试表,用
ls -l /data/mysql/your_db/确认.frm和.ibd文件时间戳是否更新
最容易被忽略的是 SELinux 上下文重置和 systemd 环境变量覆盖,这两个问题不会报错,只会让 MySQL 偷偷用回老路径,查日志也看不出异常。











