log_error必须在[mysqld]段中以绝对路径静态配置,重启生效;运行时SET GLOBAL无效,且需确保目录存在、mysql用户有写权限,并处理SELinux/AppArmor拦截。

log_error 必须在配置文件中静态设置,重启生效;运行时 SET GLOBAL log_error 会报错“Variable 'log_error' is a read only variable”,这条路走不通。
必须写在 [mysqld] 段里,否则静默失效
把 log_error 放在 [client]、[mysql] 或配置文件开头无段落标记处,MySQL 完全忽略——服务照常启动,日志却还在默认路径(比如 /var/lib/mysql/hostname.err 或 C:ProgramDataMySQLMySQL Server X.XDatahostname.err),且不报任何警告。
检查方法:
- 用
grep -A 5 -B 5 "log_error" /etc/my.cnf确认它紧贴在[mysqld]下方 - 如果配置文件含多个
[mysqld](如[mysqld1]),得确认你改的是实际被加载的那个段落 - Windows 下查
my.ini,同样只认[mysqld]段内的log-error
路径必须是绝对路径,且目录已存在、有写权限
log_error = error.log 或 log_error = ./error.log 是相对路径,MySQL 会把它拼到 @@datadir 下,结果日志“藏”进数据目录,你以为改了,其实没动地方。
正确做法:
- Linux:写成
log_error = /var/log/mysql/error.log,然后提前执行:sudo mkdir -p /var/log/mysql→sudo chown mysql:mysql /var/log/mysql - Windows:推荐用正斜杠避免转义问题,例如
log-error = D:/mysqllog/error.log;若用反斜杠,必须双写:log-error = D:\mysqllog\error.log - 目标目录不能是临时挂载点或 NFS 共享目录(尤其 SELinux/AppArmor 启用时),否则可能因上下文限制写入失败
SELinux 或 AppArmor 可能拦截,但错误表现极隐蔽
即使配置、路径、权限全对,CentOS/RHEL 上的 SELinux 或 Ubuntu/Debian 上的 AppArmor 仍可能阻止 mysqld 向非标准路径写日志。典型现象是:服务启动失败,systemctl status mysqld 显示 “failed”,但你翻遍默认日志都找不到明确原因。
排查步骤:
- RHEL/CentOS:
sudo setenforce 0临时关闭 SELinux,再试重启;确认有效后,永久放行:sudo setsebool -P mysqld_read_error_log on - Ubuntu:
sudo dmesg | grep -i avc | grep mysqld查是否有拒绝记录;必要时更新 AppArmor 规则 - 别跳过这步——大量线上故障卡在这儿,不是配置错,是安全模块拦住了
改完必须验证,不能只看配置文件是否保存
重启后立刻进 MySQL 执行:SHOW VARIABLES LIKE 'log_error';。返回值必须是你设的完整绝对路径。如果还是默认路径,说明前面某步没到位。
进一步确认:
- 用
tail -f /your/specified/path/error.log实时观察,手动触发一次mysqladmin shutdown再启,看 “Shutdown complete” 是否出现在新路径 - 旧日志文件不会自动迁移,也不会被覆盖或删除,需人工归档或清理
-
log_error不记录 SQL 错误(如ERROR 1062),只记服务级事件(启动/崩溃/插件加载失败等);想抓 SQL 层异常,得靠应用日志或general_log
mysqld 进程实际以哪个用户身份运行。这些点串起来,才是线上环境改日志路径的真实门槛。


















