AppArmor配置未精准匹配MySQL实际路径与操作权限导致拒绝访问;需用dmesg定位缺失规则,按operation类型(open/mknod等)和name路径补全对应rw/**规则,并确保目录属主为mysql:mysql。

MySQL服务启动失败、日志里反复出现 apparmor="DENIED",基本就是AppArmor配置没对上——不是配不配的问题,是配得准不准的问题。
为什么刚装完MySQL就报AppArmor拒绝访问?
Ubuntu 20.04+ 默认启用AppArmor,且预装了 /etc/apparmor.d/usr.sbin.mysqld 这个基础配置文件。但这个文件只覆盖默认路径(/var/lib/mysql/**、/etc/mysql/** 等),一旦你改过数据目录、日志路径、临时文件位置,或用了自定义socket路径,AppArmor立刻拦截——它不猜意图,只认规则。
典型错误日志里会出现这些关键词:
-
operation="mknod"(尝试创建临时文件失败) -
operation="open"(打不开新指定的error log) -
name="/opt/mysql/data/..."(路径完全不在原规则里)
如何快速定位缺失的AppArmor规则?
别靠猜。直接让AppArmor自己“说话”:
- 先确保MySQL处于
Complaining模式:sudo aa-complain /usr/sbin/mysqld - 启动MySQL:
sudo systemctl start mysql - 立即查拒绝记录:
sudo dmesg | grep -i "apparmor.*denied" | tail -20
输出会明确告诉你哪条操作被拒、访问哪个路径、需要什么权限(r、w、rw、ix)。比如看到 name="/data/mysql/tmp/" 被拒,就说明要加一行 /data/mysql/tmp/** rw,。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
修改AppArmor配置时必须注意的三件事
直接编辑 /etc/apparmor.d/usr.sbin.mysqld 是最常用方式,但以下细节决定成败:
- 路径末尾的
**不可省略:写成/var/log/mysql/ r,只允许读目录本身;而/var/log/mysql/** r,才能读里面所有文件和子目录 - 权限粒度要匹配实际行为:MySQL写error log需要
rw,但只读配置文件只需r;临时文件目录必须带w和mknod权限(AppArmor里用rw隐含支持mknod) - 加载前必须语法检查:
sudo apparmor_parser -t /etc/apparmor.d/usr.sbin.mysqld(-t表示试加载,不生效,仅校验语法);校验通过再执行sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld
常见自定义场景下的规则补丁
如果你改过默认路径,下面这些规则片段可以直接加进配置文件对应位置(放在 profile /usr/sbin/mysqld { 大括号内):
- 数据目录移到
/data/mysql:/data/mysql/ r, /data/mysql/** rw, - 错误日志写到
/var/log/mysql-custom/error.log:/var/log/mysql-custom/error.log rw, - 启用慢查询日志到
/data/mysql/logs/slow.log:/data/mysql/logs/ rw, /data/mysql/logs/** rw, - 使用自定义socket文件
/run/mysqld-custom/mysqld.sock:/run/mysqld-custom/ rw, /run/mysqld-custom/** rw,
注意:所有新增路径都必须存在且属主为 mysql:mysql,否则即使AppArmor放行,MySQL自身也会因权限不足退出。
AppArmor真正难的不是写规则,而是确认MySQL到底在哪些路径上做了哪些系统调用——dmesg 日志里的 operation 字段,比任何文档都准。

















