ITPub最近搞了个IT新媒体影响力年度评选,还是选择的拉票,虽然有些扰人,但还是贴到这,顺其自然,如果各位方便的,登录网址或者扫这个二维码,https://zt.itpub.net/topic/peanit/

搜索"bisal",点击"立即投票",PC端和手机端都可以每天点10次,即每天可以投20票,在此谢谢各位

言归正传,技术社群的这篇文章《MY-013129 的报错信息为何会不一样?》给我们讲了一个MySQL数据库中没有固定错误信息的错误号,错误信息对于应用系统来说是很重要的,写好用好都是有些讲究的。
一个没有固定信息的报错
你是否了解 MY-013129 报错?
该错误与其他错误最大的区别,就是没有固定的错误信息。
可能是下面这条严重的权限错误。
2025-03-03T15:38:08.918103+08:00 0 [ERROR] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-000001 - Can't create/write to file '/opt/mysql/data/3307/mysqld.pid' (OS errno 13 - Permission denied)
也可能是一些不严重的错误。
2024-11-28T14:51:09.590102Z 0 [ERROR] [MY-013129] [Server] A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-004031 - The client was disconnected by the server because of inactivity. See wait_timeout and interactive_timeout for configuring this behavior.'
那 MySQL 官网是怎么解释的?
官网的定义
查看官网 相关说明[1],仅给出了对应的错误格式定义。
Error number: MY-013129; Symbol: ER_SERVER_NO_SESSION_TO_SEND_TO; SQLSTATE: HY000
Message: A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-%06d - %s
代码的逻辑
那么究竟什么场景会触发该错误呢?以 MySQL 8.0.28 代码为例,可观察到以下定义:
代码文件:mysql-8.0.28\share\messages_to_error_log.txt
定义内容
ER_SERVER_NO_SESSION_TO_SEND_TO eng "A message intended for a client cannot be sent there as no client-session is attached. Therefore, we're sending the information to the error-log instead: MY-%06d - %s"
继续查看对应的输出逻辑:
/*
Caller wishes to send to client, but none is attached, so we send
to error-log instead.
*/
else if (!thd) {
LogEvent()
.type(LOG_TYPE_ERROR)
.subsys(LOG_SUBSYSTEM_TAG)
.prio(ERROR_LEVEL)
.errcode((error < ER_SERVER_RANGE_START)
? ER_SERVER_NO_SESSION_TO_SEND_TO
: error)
.lookup(ER_SERVER_NO_SESSION_TO_SEND_TO, error, str);
}
结合代码可以总结出 MY-013129 出现的场景:
仅 8.0 版本存在 ER_SERVER_NO_SESSION_TO_SEND_TO
,故该日志仅在 MySQL 8.0 版本出现。向 client 发送消息但无可用的会话时(代码中 (!thd)
判断),会将对应的消息发送到错误日志,且日志严重级别为 ERROR(代码中由prio
指定)。
或许有些同学仅遇到过非严重错误的场景,疑惑 为何 MySQL 官方要将该日志级别配置为 ERROR?
结合个人遇到的一些场景猜测,当 MySQL 需要将该类消息发送到错误日志时,因为实际后半段错误代码不同,可能为 ERROR
级别的严重错误,也可能为 WARNING
级别的警告信息,故 MySQL 直接将其配置为 ERROR
级别,从而防止误判。(以上推断仅代表个人意见,欢迎交流拍砖!)
处理的建议
首先,此类日志的重点在于其后半部分,可能包含一些关键的错误信息,因此不建议直接屏蔽。
当然,你也可以通过相关配置来屏蔽 MY-013129 错误。与其说屏蔽,不如将其作为一种 MySQL 错误日志过滤的通用思路。
MySQL 8.0.13 新增了 log_error_suppression_list
变量,但仅用于在错误日志中抑制 WARNING
或 INFORMATION
级别的日志,因此,无法通过配置 log_error_suppression_list
来抑制此类日志。这里提供另外两种思路:
1. 屏蔽关键字
通过修改监控对应的日志采集规则/代码,屏蔽掉 MY-013129 关键字。
更优的做法是多加一层判断,当匹配到 MY-013129 关键字后,进一步判断后续的错误代码,从而更加准确地进行不同级别的逻辑处理。
2. 参数 log_filter_dragnet 配置
通过配置 log_filter_dragnet
(8.0 特性)来阻止此类信息写入 MySQL 的错误日志。
配置方式可参考:
-- 安装组件
INSTALL COMPONENT 'file://component_log_filter_dragnet';
SET GLOBAL log_error_services = 'log_filter_dragnet; log_sink_internal';
-- 配置规则
SET GLOBAL dragnet.log_error_filter_rules =
'IF prio == ERROR and err_code == ER_SERVER_NO_SESSION_TO_SEND_TO THEN drop.';
-- 取消配置
SET GLOBAL log_error_services = 'log_filter_internal; log_sink_internal';
UNINSTALL COMPONENT 'file://component_log_filter_dragnet';
官网的相关说明: https://dev.mysql.com/doc/mysql-errors/8.0/en/server-error-reference.html
如果您认为这篇文章有些帮助,还请不吝点下文章末尾的"点赞"和"在看",或者直接转发朋友圈,

微信公众号:@bisal的个人杂货铺 腾讯云开发者社区:@bisal的个人杂货铺 头条号:@bisal的个人杂货铺 CSDN:@bisal ITPub:@bisal 墨天轮:@bisal 51CTO:@bisal 小红书:@bisal 抖音:@bisal




