错误日志包含 mysqld 在启动和关闭时的记录,以及诊断消息,如 errors、warnings 和 notes,需要重点关注的是 error 级别。
错误消息也可能会填充到 Performance_schema.error_log 表中。
如果以 mysqld_safe 启动,可能会将消息写入错误日志。
错误日志组件
MySQL 8.0 版本的错误日志是基于组件的。
过滤器 (filter)
过滤器修改由这个变量值中的组件发现的日志事件。
- log_filter_internal
- 内置组件,无需加载。不能多次使用
- 可以结合 log_error_verbosity 和 log_error_suppression_list 系统变量,提供基于日志事件优先级和错误代码的错误日志过滤
- log_filter_dragnet
- 用于自定义过滤规则的组件。不能多次使用
-
URN
file://component_log_filter_dragnet
- 可以结合 dragnet.log_error_filter_rules 系统变量,提供基于用户自定义规则的错误日志过滤
接收器 (sink)
接收器将日志事件处理为具有特定格式的日志消息,并将这些消息写入其关联的输出,例如文件或系统日志。
- log_sink_internal
- 内置组件,无需加载。不能多次使用
-
提供系统表 performance.error_log 的支持
-
输出格式
- 传统的错误日志输出
2020-08-06T14:25:02.835618Z 0 [Note] [MY-012487] [InnoDB] DDL log recovery : begin 2020-08-06T14:25:02.936146Z 0 [Warning] [MY-010068] [Server] CA certificate /var/mysql/sslinfo/cacert.pem is self signed. 2020-08-06T14:25:02.963127Z 0 [Note] [MY-010253] [Server] IPv6 is available. 2020-08-06T14:25:03.109022Z 5 [Note] [MY-010051] [Server] Event Scheduler: scheduler thread started with id 5
- 字段
time thread [label] [err_code] [subsystem] msg
- 传统的错误日志输出
- log_sink_json
- 以 JSON 格式输出。可以多次使用
-
URN
file://component_log_sink_json
- 提供系统表 performance.error_log 的支持
-
输出格式
- 生成为包含键值对的 JSON 对象
{ "prio": 3, "err_code": 10051, "source_line": 561, "source_file": "event_scheduler.cc", "function": "run", "msg": "Event Scheduler: scheduler thread started with id 5", "time": "2020-08-06T14:25:03.109022Z", "ts": 1596724012005, "thread": 5, "err_symbol": "ER_SCHEDULER_STARTED", "SQL_state": "HY000", "subsystem": "Server", "buffered": 1596723903109022, "label": "Note" }
- 字段
ts:时间戳
buffered:时间戳 -
时间戳转换
mysql> SET time_zone = '+00:00'; mysql> SELECT FROM_UNIXTIME(1596724012005/1000.0); +-------------------------------------+ | FROM_UNIXTIME(1596724012005/1000.0) | +-------------------------------------+ | 2020-08-06 14:26:52.0050 | +-------------------------------------+ mysql> SELECT FROM_UNIXTIME(1596723903109022/1000000.0); +-------------------------------------------+ | FROM_UNIXTIME(1596723903109022/1000000.0) | +-------------------------------------------+ | 2020-08-06 14:25:03.1090 | +-------------------------------------------+
- 生成为包含键值对的 JSON 对象
- log_sink_syseventlog
- 记入系统日志 (syslog)。不能多次使用
-
URN
file://component_log_sink_syseventlog
- log_sink_test
- 用于编写测试用例的内部使用,而不用于生产。
-
URN
file://component_log_sink_test
- Early-Startup
- 服务器在处理启动选项之前,会生成一些错误日志消息。
配置方法
功能
- 日志事件可以由过滤器组件过滤,以影响可用于写入的信息。
- 日志事件由接收器 (写入器) 组件输出。
- 可以启用多个接收器组件,以将错误日志输出写入多个目标。
- 内置的过滤器和接收器组件结合在一起以实现默认的错误日志格式。
- 可加载的接收器允许以 JSON 格式记录或记录到系统日志
- 系统变量控制要启用的日志组件以及每个组件的运行方式。
系统变量
-
log_error_services
- 控制错误日志使用的组件
-
变量值
- 0:禁用
-
列表:多个元素用分号或逗号分隔。
mysql> SELECT @@GLOBAL.log_error_services; -- 默认值 +----------------------------------------+ | @@GLOBAL.log_error_services | +----------------------------------------+ | log_filter_internal; log_sink_internal | +----------------------------------------+
Note: 以上两个组件都是内置组件。
- 组件顺序很重要,因为服务器按照列出的顺序执行组件。
-
过滤器必须放在接收器之前。
-
接收器可以配置多个。
-
示例
- 配置两个接收器组件,一个接收器接收所有事件,一个接收器接收过滤后的事件
log_sink_1; log_filter_internal; log_sink_2
- 配置两个接收器组件,两个接收器都接收过滤后的事件
log_filter_internal; log_sink_1; log_sink_2
- 配置两个接收器组件,一个接收器接收所有事件,一个接收器接收过滤后的事件
- log_error_verbosity
- 控制日志的详细程度。
- 变量值
- 1:仅记录 errors
- 2:(默认) 记录 errors 和 warnings
- 3:记录 errors、warnings、information/note
- log_error_suppression_list
- 控制不记录哪些事件 (日志事件黑名单)
-
只抑制 WARNING/INFORMATION 的事件,不会抑制优先级为 ERROR/SYSTEM 的消息
-
变量值
- 空字符串
-
列表:错误代码 (符号或数字形式,数字代码可以不带
MY-
前缀) 之间用逗号分隔。一般使用符号形式,更易读。ER_SERVER_SHUTDOWN_COMPLETE MY-000031 000031 MY-31 31
- 全局错误代码:1-999,服务器和客户端使用
- 服务器错误代码:>10000,服务器使用,不发送给客户端
- log_error
- 控制默认错误日志的输出目标
- 变量值
- 空值:默认目标是控制台 (标准错误输出 stderr)
- 未命名文件:输出目标为数据目录下 host_name.err 文件
- 指定文件名:默认在数据目录下生成一个 .err 后缀的文件。通常错误日志放在 /var/log/ 下
- 对日志接收器的影响
- 如果变量值是 stderr
- log_sink_internal,log_sink_json,log_sink_test
- 这些接收器写入控制台
- log_sink_syseventlog
- 此接收器写入系统日志,与 log_error 值无关
- log_sink_internal,log_sink_json,log_sink_test
- 如果变量值不是 stderr
- log_sink_internal,log_sink_test
- 这些接收器写入 file_name
- log_sink_json
- 此接收器将写入文件 file_name 加上编号的 .NN.json 后缀,如 file_name.00.json,file_name.01.json 等。
- log_sink_syseventlog
- 此接收器写入系统日志,与 log_error 值无关
- log_sink_internal,log_sink_test
- 如果变量值是 stderr
- log_timestamps
控制日志 (包括常规日志、错误日志和慢查询日志) 中时间戳的时区。
- 日志的时间戳格式
- 时间戳采用 ISO 8601/RFC 3339 格式
YYYY-MM-DDThh:mm:ss.uuuuuu
加一个结尾符号2021-02-01T00:39:31.438390Z 2021-02-01T14:48:52.935812+08:00
- 时间戳采用 ISO 8601/RFC 3339 格式
- 变量值
- UTC
- (默认) 时间戳以
Z
结尾
- (默认) 时间戳以
- SYSTEM
- 时间戳以
±hh:mm
结尾
- 时间戳以
- UTC
- 日志的时间戳格式
添加或删除日志组件
- 添加组件
- 使用 INSTALL COMPONENT 手动加载
- 如果组件是内置的或已经加载的,不需要再次手动加载
-
加载组件会将其注册到 mysql.component 系统表中,以便服务器自动加载它以用于后续启动
mysql> select * from mysql.component; +--------------+--------------------+---------------------------------------+ | component_id | component_group_id | component_urn | +--------------+--------------------+---------------------------------------+ | 1 | 1 | file://component_log_sink_syseventlog | +--------------+--------------------+---------------------------------------+
- 把组件添加到系统变量 log_error_services 中
- 修改配置文件
- 持久化设置
- 使用 INSTALL COMPONENT 手动加载
- 删除组件
- 使用 UNINSTALL COMPONENT 删除组件
- 示例
- 使用系统日志接收器组件 (log_sink_syseventlog) 组件替换默认的接收器组件
mysql> install component 'file://component_log_sink_syseventlog'; mysql> set global log_error_services='log_filter_internal; log_sink_syseventlog';
Note: URN语法,
INSTALL COMPONENT 'file://component_组件名称';
- 系统变量
log_syslog8.0 版本已弃用,改为使用组件的方式。
把错误日志发送到系统日志上
- syseventlog.facility
8.0.13 版本之前,使用 log_syslog_facility。
- syslog 消息的默认功能是守护程序 (daemon)。设置此变量以指定其他功能
- syseventlog.include_pid
8.0.13 版本之前,使用 log_syslog_include_pid。
- 是否在 syslog 输出的每一行中包含服务器进程ID
- syseventlog.tag
8.0.13 版本之前,使用 log_syslog_tag。
- 将
mysqld
作为一个标识符添加到 syslog 中
- 将
- 系统变量
- 配置多个接收器组件
mysql> set global log_error_services='log_filter_internal; log_sink_internal; log_sink_syseventlog';
- 查看系统日志
[root@yingzai ~]$ more /var/log/messages Mar 16 15:57:41 yingzai systemd[1]: Stopping MySQL Server... Mar 16 15:57:41 yingzai mysqld[123315]: Received SHUTDOWN from user . Shutting down mysqld (Version: 8.0.23). Mar 16 15:57:43 yingzai mysqld[123315]: /opt/mysql/bin/mysqld: Forcing close of thread 8 user: 'root'. Mar 16 15:57:43 yingzai mysqld[123315]: /opt/mysql/bin/mysqld: Forcing close of thread 9 user: 'root'. Mar 16 15:57:43 yingzai mysqld[123315]: /opt/mysql/bin/mysqld: Forcing close of thread 10 user: 'root'. Mar 16 15:57:44 yingzai mysqld[123315]: /opt/mysql/bin/mysqld: Shutdown complete (mysqld 8.0.23) MySQL Comm unity Server - GPL. Mar 16 15:57:44 yingzai systemd[1]: mysqld.service: Succeeded. Mar 16 15:57:44 yingzai systemd[1]: Stopped MySQL Server. Mar 16 15:57:44 yingzai systemd[1]: Started MySQL Server. Mar 16 15:57:46 yingzai systemd[1]: mysqld.service: Main process exited, code=exited, status=1/FAILURE Mar 16 15:57:46 yingzai systemd[1]: mysqld.service: Failed with result 'exit-code'.
- 查看系统日志
- 恢复默认组件,并卸载多余组件
mysql> set global log_error_services = default; mysql> uninstall component 'file://component_log_sink_syseventlog';
- 使用 JSON 格式的接收器
mysql> install component 'file://component_log_sink_json'; mysql> set persist log_error_services='log_filter_internal; log_sink_internal; log_sink_json';
- 查看日志文件
[root@yingzai mysql]$ ll total 16 -rw-r----- 1 mysql mysql 4268 Mar 16 16:20 err.log -rw-r----- 1 mysql mysql 6338 Mar 16 16:20 err.log.00.json
- 查看日志文件
- 使用系统日志接收器组件 (log_sink_syseventlog) 组件替换默认的接收器组件
错误事件字段
核心字段
- time
- 事件时间戳,精度为微秒
- msg
- 内容
- prio
- 事件优先级
事件优先级可以是数字或字符串,比如优先级为2的事件,字符串表示为 ‘Warning’。
-
包括
- 0:System event
- 1:Error event
- 2:Warning event
- 3:Note/information event
- 事件优先级
- err_code
- 错误代码,如1022
- err_symbol
- 事件错误符号,字符串形式,如’ER_DUP_KEY’
- SQL_state
- 事件的 SQLSTATE 值,字符串形式,如 ‘23000’
- subsystem
- 发生事件的子系统
- 可能的值是
- InnoDB
- Repl
- Server (其他)
可选字段
- 错误的其他信息
- OS_errno
- 操作系统的错误号码
- OS_errmsg
- 操作系统的错误信息
- label
- 与 prio 值相对应的标签,为字符串
- OS_errno
- 标识事件发生的客户端
- user
- 客户端用户
- host
- 客户端主机名
- thread
- 产生错误事件的线程 ID
- query_id
- 查询 ID
- user
- 调试信息
- source_file
- 发生事件的源文件,没有任何前导路径
- source_line
- 源文件中发生事件的行
- function
- 发生事件的函数
- component
- 发生事件的组件或插件
- source_file
自定义字段
- 略
错误日志的过滤方式
错误日志可以通过不同的过滤器组件,实现不同的过滤方式。
基于优先级的过滤
log_filter_internal 日志过滤器组件根据错误事件优先级和错误代码实现简单形式的日志过滤。
这种过滤方式是通过以下两个系统变量来实现的。
- log_error_verbosity
- 错误日志的详细度
- log_error_suppression_list
- 错误日志抑制列表
基于规则的过滤
log_filter_dragnet 日志过滤器组件可根据用户自定义规则启用日志过滤。
- 开启组件
mysql> install component 'file://component_log_filter_dragnet'; mysql> set global log_error_services='log_filter_dragnet; log_sink_internal';
- 卸载组件
SET GLOBAL log_error_services = default; UNINSTALL COMPONENT 'file://component_log_filter_dragnet';
- 系统变量
- dragnet.log_error_filter_rules
- 指定过滤规则
-
每个过滤规则都是以英文句号
.
结尾的 IF 语句。不区分大小写。SET GLOBAL dragnet.log_error_filter_rules = ' IF prio>=INFORMATION THEN drop. IF EXISTS source_line THEN unset source_line. ';
Note: 为了方便阅读,可以每个规则占用一行。
-
示例
- 60秒一个事件
SET GLOBAL dragnet.log_error_filter_rules = 'IF prio>=INFORMATION THEN throttle 1/60.';
- 60秒一个事件
- dragnet.log_error_filter_rules
- 过滤规则的语法
rule: IF condition THEN action [ELSEIF condition THEN action] ... [ELSE action] . condition: { field comparator value | [NOT] EXISTS field | condition {AND | OR} condition } action: { drop | throttle {count | count / window_size} | set field [:= | =] value | unset [field] } field: { core_field | optional_field | user_defined_field } core_field: { time | msg | prio | err_code | err_symbol | SQL_state | subsystem } optional_field: { OS_errno | OS_errmsg | label | user | host | thread | query_id | source_file | source_line | function | component } user_defined_field: sequence of characters in [a-zA-Z0-9_] class comparator: {== | != | | >= | => | <= | =< | } value: { string_literal | integer_literal | float_literal | error_symbol | priority } count: integer_literal window_size: integer_literal string_literal: sequence of characters quoted as '...' or "..." integer_literal: sequence of characters in [0-9] class float_literal: integer_literal[.integer_literal] error_symbol: valid MySQL error symbol such as ER_ACCESS_DENIED_ERROR or ER_STARTUP priority: { ERROR | WARNING | INFORMATION }
- 可以使用 AND、OR 运算符
-
转义字符串可以使用反斜杠 (\)
-
事件优先级的比较可以使用数字或字符串
IF prio == INFORMATION THEN ... IF prio == 3 THEN ...
- 错误代码可以使用数字形式或符号形式
IF err_code == ER_STARTUP THEN ... IF err_code == 1408 THEN ...
- 查看错误代码的数字和符号的对应关系
- 查看参考手册
-
perror 命令
-- 数字形式的错误代码 IF err_code == 10927 OR err_code == 10914 THEN drop. IF err_code == 1131 THEN drop. -- 查看对应的符号形式 shell> perror 10927 10914 1131 MySQL error code MY-010927 (ER_ACCESS_DENIED_FOR_USER_ACCOUNT_LOCKED): Access denied for user '%-.48s'@'%-.64s'. Account is locked. MySQL error code MY-010914 (ER_ABORTING_USER_CONNECTION): Aborted connection %u to db: '%-.192s' user: '%-.48s' host: '%-.64s' (%-.64s). MySQL error code MY-001131 (ER_PASSWORD_ANONYMOUS_USER): You are using MySQL as an anonymous user and anonymous users are not allowed to change passwords -- 符号形式的错误代码 IF err_code == ER_ACCESS_DENIED_FOR_USER_ACCOUNT_LOCKED OR err_code == ER_ABORTING_USER_CONNECTION THEN drop. IF err_code == ER_PASSWORD_ANONYMOUS_USER THEN drop.
- 查看错误代码的数字和符号的对应关系
- 过滤规则的动作
- drop
- 删除当前的日志事件 (不记入日志)
- throttle
- 应用速率限制以减少符合特定条件的事件的日志详细程度
-
速率形式
- count 或 count/window_size
- 计数值表示每个时间窗口允许记录的事件发生数
- window_size 值是时间窗口,以秒为单位。默认60秒。
- count 或 count/window_size
- 示例
- 将插件关闭消息限制为每60秒出现5次
IF err_code == ER_PLUGIN_SHUTTING_DOWN_PLUGIN THEN throttle 5.
- 将错误和警告限制为每小时发生1000次,将信息消息限制为每小时发生100次
IF prio WARNING THEN drop.
- 将插件关闭消息限制为每60秒出现5次
- err_code
IF err_code == ER_ACCESS_DENIED_ERROR THEN ... IF err_code == 1045 THEN ...
- err_symbol
-
可选字段
- label
-
source_file
IF source_file == "distance.cc" THEN ...
- drop
错误日志文件刷新和重命名
错误日志刷新
- flush error logs 或 flush logs
- mysqladmin flush-logs
错误日志重命名 (轮换)
错误日志重命名后,需要刷新一下,刷新后自动生成新的日志文件。
mv host_name.err host_name.err-old
mysqladmin flush-logs
mv host_name.err-old backup-directory