先说一个核心要点:MySQL 8.0 和 5.7 在日志处理机制上存在显著差异——8.0 不会自动将错误日志输出到系统 syslog。无论你运行的是 Linux rsyslog 还是 systemd-journald,都需要手动指定“写入 syslog”。这并非简单修改配置文件参数就能完成,必须通过组件机制逐步配置。

关键前提:必须显式启用,默认不会写入 syslog
MySQL 8.0 的 log_error_services 默认值中根本不含 syslog 组件,启动后只会将日志写入 hostname.err 文件。这与 5.7 的自动对接完全不同——5.7 只需安装 rsyslog,日志就会自动传递。而在 8.0 中,你必须手动将 syslog 写入器插入日志处理链,否则无法实现。
两步操作:INSTALL COMPONENT + SET PERSIST
8.0 采用组件架构控制日志输出,启用 syslog 只需两步:先加载组件,再激活。注意,不能只改配置文件,必须执行 SQL 命令:
INSTALL COMPONENT 'file://component_log_sink_syseventlog';—— 加载 syslog 写入器组件。务必带上file://前缀,并确保组件文件位于正确的目录。SET PERSIST log_error_services = 'log_filter_internal; log_sink_syseventlog';—— 替换默认链,将内部文件写入器替换为 syslog 写入器。此命令立即生效,PERSIST会将配置写入mysqld-auto.cnf,重启后自动加载。
如果只想临时测试效果,可以使用 SET GLOBAL,但重启后配置会失效——生产环境不推荐这种做法。
配置 log_error_services 的三个常见陷阱
该变量是一个分号分隔的字符串,顺序决定处理流程。以下三个陷阱经常导致问题:
- 遗漏过滤器: 如果只写
log_sink_syseventlog,日志根本不会出现——至少需要配置一个过滤器,log_filter_internal是最简单有效的选择。 - 拼写错误: 组件名区分大小写,
log_sink_syseventlog误写为log_sink_syslog或log_sink_eventlog会立即报错。 - 残留旧组件: 之前启用过
log_sink_internal但未显式移除,两条 sink 会同时工作——既写文件又写 syslog,导致双倍 I/O 且日志翻倍,排查问题时容易混淆。
如何查看当前配置?执行 SELECT @@global.log_error_services;,返回值中只保留你实际需要的组件即可。
Linux 下 syslog 的行为由 syseventlog.* 变量控制
写入 syslog 后,消息格式、来源标识、设施(facility)等细节并非完全由 /etc/rsyslog.conf 决定,MySQL 自身拥有控制变量:
syseventlog.facility:默认为daemon,可改为local0~local7以方便 rsyslog 路由(例如SET PERSIST syseventlog.facility = 'local5';)。syseventlog.tag:定义日志前缀,设为'mysql-prod'后,日志行会显示为mysqld-mysql-prod,便于区分不同实例。syseventlog.include_pid:设为ON可在每行添加进程 ID,多实例部署时排查问题尤为实用。
需要留意:这些变量仅适用于 MySQL 8.0.13 及以上版本;旧版本需使用 log_syslog_facility 等兼容名称,混用会导致报错。版本不同,命名规则也不同。
真正棘手的往往不是命令本身,而是组件加载失败时缺乏明确报错。INSTALL COMPONENT 返回成功,并不代表组件已生效——必须去 error log 中查找 Component 'log_sink_syseventlog' installed 这样的确认行,否则后续 log_error_services 的设置将无法生效。这个细节曾让许多人卡住,值得特别关注。
