答案是datadir权限或AppArmor拦截导致,需停服务后递归chown -R mysql:mysql /path、chmod 750 /path,并更新AppArmor规则为新路径。

MySQL启动失败但日志只报“Permission denied”(errno 13)
这基本就是datadir权限或安全模块拦住了——不是配置写错了,是系统根本不让mysqld进程碰那个目录。Ubuntu和CentOS对权限管控逻辑不同,迁移后直接照搬CentOS的chown/chmod习惯会踩坑。
先停服务:sudo systemctl stop mysql,再查真实datadir路径:sudo mysqld --verbose --help 2>/dev/null | grep "datadir"。别信配置文件里写的,mysqld实际读的是哪个路径,才是关键。
- 输出类似
datadir /data/mysql,就用这个路径;如果没输出,说明my.cnf加载失败,先查sudo mysqld --verbose --help | grep "Default options"确认生效配置位置 -
ls -ld /data/mysql看属主,99%是root:root或迁移时残留的旧用户 -
ls -l /data/mysql/mysql/ | head -3看内部子目录归属,InnoDB初始化要遍历整个树,顶层改了没用
chown和chmod必须递归且严格匹配MySQL 8.0+要求
Ubuntu默认装的是MySQL 8.x,它启动时会校验整个datadir树的归属和权限,宽松了直接拒启。
- 执行:
sudo chown -R mysql:mysql /data/mysql—— 必须用mysql:mysql,不能root:mysql或mysql:root,否则mysql.plugin表加载失败 - 执行:
sudo chmod 750 /data/mysql—— 注意是750,不是755或777;750表示属主可读写执行、属组可读执行、其他人无权访问 - 子目录权限自动继承,不用单独
chmod -R,反而可能破坏InnoDB表空间权限一致性
Ubuntu必须处理AppArmor,CentOS的SELinux经验在这里不适用
这是迁移后最常漏掉的一环:Ubuntu默认启用AppArmor,而CentOS用SELinux。AppArmor规则硬编码了旧路径,不改它,chown/chmod全白做。
- 查状态:
sudo aa-status,确认AppArmor在运行且usr.sbin.mysqld处于enforce模式 - 编辑:
sudo nano /etc/apparmor.d/usr.sbin.mysqld - 找到类似这两行:
#/var/lib/mysql/ r, #/var/lib/mysql/** rwk,
替换成你的新路径,比如:
/data/mysql/ r, /data/mysql/** rwk,
- 重载策略:
sudo systemctl restart apparmor(Ubuntu 22.04+)或sudo /etc/init.d/apparmor reload(老版本)
检查my.cnf加载顺序和socket路径是否同步更新
Ubuntu的MySQL配置分散在多个位置,/etc/mysql/my.cnf只是入口,真正生效的可能是/etc/mysql/mysql.conf.d/mysqld.cnf或/etc/mysql/conf.d/下的文件。
- 确认
datadir只在一处定义:sudo grep -r "datadir" /etc/mysql/ - 检查
socket路径是否也改了:sudo grep "socket" /etc/mysql/mysql.conf.d/mysqld.cnf,如果datadir移到/data/mysql,socket通常也要对应移到/data/mysql/mysql.sock,否则客户端连不上 - 重启前删掉旧socket:
sudo rm -f /var/run/mysqld/mysqld.sock,避免残留文件干扰
AppArmor路径没改、socket没同步、或者chmod用了755——这三个点任何一个漏掉,都会让MySQL卡在启动第一秒,日志里只留一句“Permission denied”。


















