MySQL错误日志Permission denied的根本原因是运行用户mysql对日志路径无读写权限,需检查目录/文件属主与权限;SELinux/AppArmor、MySQL 8.0日志服务配置及容器UID映射亦常导致该问题。

MySQL 错误日志文件被拒绝访问(Permission denied)
常见现象是 MySQL 启动失败,或 mysqld 进程反复崩溃,错误日志本身却写不进去;查看系统日志(如 /var/log/syslog 或 journalctl -u mysql)会看到类似 Can't open error log '/var/log/mysql/error.log': Permission denied 的报错。
根本原因不是 MySQL 配置错了路径,而是运行 mysqld 的系统用户(通常是 mysql)对日志目标目录或文件没有读写权限。尤其在手动创建日志文件、修改过日志路径、或用 root 初始化后未修正属主时极易发生。
- 确认日志路径:查
my.cnf中的log_error值,例如log_error = /var/log/mysql/error.log - 检查父目录权限:运行
ls -ld /var/log/mysql,确保该目录属主为mysql:mysql,且至少有drwxr-x---(即目录可进入、可写) - 检查文件权限:若
error.log已存在,运行ls -l /var/log/mysql/error.log,属主必须是mysql;若属主是root,mysqld无法追加写入 - 修复命令示例:
sudo chown -R mysql:mysql /var/log/mysql<br>sudo chmod 750 /var/log/mysql
systemd 环境下 MySQL 日志目录被 SELinux 或 AppArmor 拦截
在 CentOS/RHEL(启用 SELinux)或 Ubuntu(启用 AppArmor)上,即使文件权限全对,仍可能因安全模块阻止写入。此时 mysqld 启动日志里看不到明确的“Permission denied”,但 journalctl -u mysql 会显示 AVC denial 或 AppArmor “DENIED” 记录。
- SELinux 场景:运行
sudo ausearch -m avc -ts recent | grep mysqld,若看到avc: denied { write } for ... path="/var/log/mysql/error.log",说明被拦 - 临时放行(仅用于验证):
sudo setenforce 0,再试启动 MySQL;若成功,则确认是 SELinux 导致 - 永久修复:用
sudo semanage fcontext -a -t mysqld_log_t "/var/log/mysql(/.*)?",然后sudo restorecon -Rv /var/log/mysql - AppArmor 场景:检查
/etc/apparmor.d/usr.sbin.mysqld是否包含对应日志路径的写权限规则,例如/var/log/mysql/** rw,;修改后执行sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.mysqld
MySQL 8.0+ 使用内置错误日志组件时权限逻辑变化
MySQL 8.0 起默认启用 log_error_services,错误日志可能由多个服务协同输出(如 log_filter_internal + log_sink_file),而 log_error 只控制最终文件路径。如果配置了 log_error_services = 'log_filter_internal; log_sink_json',但没配 log_sink_file,就可能静默跳过文件写入 —— 表现为“没报错、也没日志”,容易误判成权限问题。
- 确认当前生效的日志服务:
SELECT @@log_error_services; - 若想回退到传统文件日志,设为:
SET PERSIST log_error_services = 'log_filter_internal; log_sink_file'; - 注意
log_sink_file依赖log_error指向的路径,仍需保证该路径权限正确 - 不要混用 JSON 和 file sink 到同一文件,会导致内容损坏或写入失败
容器化部署中挂载日志路径的权限陷阱
Docker 或 Kubernetes 中挂载宿主机目录到容器内 /var/log/mysql 时,容器内 mysql 用户(UID 999 或 27)往往与宿主机对应 UID 不匹配,导致容器内无权写入挂载点。
- 宿主机上先创建目录并设好 UID:
sudo mkdir -p /host/mysql-logs && sudo chown 999:999 /host/mysql-logs(查镜像文档确认实际 UID) - 避免用
:z或:Z标签强制 relabel SELinux 上下文,除非明确需要;否则优先用:rw并手动 fix 权限 - Kubernetes 中,可通过
securityContext.runAsUser显式指定 UID,并配合initContainer在启动前chown宿主机挂载路径 - 更稳妥的做法:让容器内 MySQL 写日志到
/tmp或/dev/stderr,由容器运行时统一收集,绕过挂载权限问题
MySQL 错误日志权限问题本质是「运行用户」和「路径属主」的对齐问题,但实际排查时容易卡在 SELinux/AppArmor、容器 UID 映射、或 8.0 新日志架构这些隐性层面上。动手前先看 journalctl -u mysql 的第一行真实报错,比盲目改权限更省时间。










