mysql启动失败需先查apparmor="denied"日志,因ubuntu 22.04默认启用apparmor,修改datadir、log_error等路径后即使权限正确也会被拦截;应编辑/etc/apparmor.d/usr.sbin.mysqld添加对应rwk或w规则并重载策略。

为什么 MySQL 启动失败时要先看 apparmor="DENIED" 日志
Ubuntu 22.04 默认启用 AppArmor,而 MySQL 的 mysqld 进程被限制在 /usr/sbin/mysqld 策略下运行。一旦你修改了数据目录、日志路径或 socket 文件位置,AppArmor 就会拦截对新路径的访问——哪怕权限和属主都正确。典型表现是 systemctl start mysql 立即失败,journalctl -xe 里反复出现 apparmor="DENIED" operation="open" 或 operation="mknod",后面跟着被拒的绝对路径(比如 /data/mysql/data/ibdata1 或 /var/log/mysql/error.log)。这不是权限问题,也不是 SELinux 干的(Ubuntu 不用它),就是 AppArmor 在守门。
如何给 MySQL 添加自定义路径的读写权限
直接编辑系统策略文件 /etc/apparmor.d/usr.sbin.mysqld 是最稳妥的方式,不推荐新建 profile(容易被覆盖或未加载)。操作前先确认当前策略是否已加载:
sudo apparmor_status | grep mysqld
如果看到 /usr/sbin/mysqld 在 “profiles are loaded” 列表里,就可以编辑:
- 用
sudo nano /etc/apparmor.d/usr.sbin.mysqld打开 - 在
{开头的大括号内、靠近末尾处插入新规则(注意缩进统一用空格) - 每条路径需明确标注权限:比如
/data/mysql/** rwk,表示递归读写创建;/var/log/mysql/error.log w,表示仅可写 - 特别注意 socket 和 pid 文件路径:若改到
/run/mysqld/mysqld.sock,得加/run/mysqld/ rw,和/run/mysqld/mysqld.sock wk, - 保存后执行
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld重载策略
哪些路径最容易被 AppArmor 拦住
不是所有路径都需要手动加,但以下几类只要动过就几乎必报错:
-
datadir:比如从默认/var/lib/mysql改到/data/mysql/data,必须加/data/mysql/data/** rwk, -
log_error:若日志不在/var/log/mysql/下(如写到/opt/mysql/log/),得加对应路径的w权限 -
socket和pid-file:若指定非标准路径(如/tmp/mysql.sock),/tmp/默认被禁止写,必须显式放开 - 临时文件目录:MySQL 8.0+ 会用
tmpdir创建临时表,若设为/data/tmp,就得加/data/tmp/** rwk,
注意:路径末尾的 ** 表示递归子目录,* 只匹配单层,别漏掉星号;权限字母顺序无关,但 k(lock)对 InnoDB 必不可少。
验证策略是否生效且没过度放权
重载策略后不要急着启动 MySQL,先做两件事:
- 运行
sudo aa-status | grep mysqld,确认 profile 状态是enforce(不是complain) - 手动触发一次访问测试:
sudo -u mysql touch /data/mysql/data/testfile,成功说明读写权限已通 - 如果仍失败,用
sudo dmesg | tail -20查最新拒绝记录,比 journalctl 更实时,能精准定位缺哪一行规则
AppArmor 策略不是“越宽越好”,比如把整个 /data/ 加 rwk 虽然能跑通,但违背最小权限原则——MySQL 进程不该有权限碰同盘下其他服务的数据目录。











