MySQL 5.7:慢查询日志缺失38%查询的原因排查
慢查询日志与Queries统计不匹配的原因及排查方向
遇到这种开启全量慢日志后仍有大量查询缺失的情况确实让人困惑,结合你给出的配置和已做的排查(排除查询缓存),我整理了几个可能的原因和对应的排查思路:
一、会话级配置覆盖了全局设置
虽然你全局开启了所有慢日志相关参数,但部分客户端会话可能通过SET语句修改了自身的慢日志配置,比如:
- 某个会话执行了
SET SESSION slow_query_log = OFF - 会话单独设置了
long_query_time为一个更大的值 - 关闭了
log_queries_not_using_indexes
排查方向:
- 实时查询所有会话的变量配置,对比是否有差异:
SELECT ID, USER, HOST, VARIABLE_NAME, VARIABLE_VALUE FROM INFORMATION_SCHEMA.PROCESSLIST JOIN INFORMATION_SCHEMA.SESSION_VARIABLES ON PROCESSLIST.ID = SESSION_VARIABLES.THREAD_ID WHERE VARIABLE_NAME IN ( 'slow_query_log', 'long_query_time', 'log_queries_not_using_indexes', 'log_slow_admin_statements' ); - 检查应用侧是否有会话级的配置修改逻辑,比如连接池初始化时的自定义设置。
二、Queries统计的口径与慢日志不一致
Queries全局状态变量统计的是所有客户端发送到MySQL的请求,其中部分请求不属于SQL查询范畴,不会被慢日志记录,常见的包括:
COM_PING请求:比如客户端定期发送的心跳包(mysqladmin ping这类操作)COM_SET_OPTION:设置连接选项的命令COM_STATISTICS、COM_STATUS:获取状态信息的命令- 部分内部维护命令:比如MySQL自身的一些后台巡检请求
排查方向:
- 查看各类
Com_*状态变量的计数,计算非查询类请求的总量:
重点关注SHOW GLOBAL STATUS LIKE 'Com_%';Com_ping、Com_set_option、Com_statistics这几个变量的数值,看它们的总和是否接近你缺失的33954条请求。 - 手动验证这类命令是否会被记录:比如执行
mysqladmin ping,然后检查慢日志是否有这条记录(大概率不会)。
三、MySQL 5.7.9版本的已知bug
你使用的MySQL 5.7.9是比较早期的5.7版本,存在一些慢日志漏记的已知问题,比如:
- 预处理语句(
PREPARE/EXECUTE)在某些场景下不被慢日志记录 - 复制链路中的部分语句漏记(尽管你开启了
log_slow_slave_statements) - 极短耗时的查询(即使
long_query_time=0)因为内部逻辑判断被跳过
排查方向:
- 查看MySQL官方的bug列表,确认5.7.9是否存在慢日志漏记的相关问题
- 临时升级到5.7系列的最新小版本(比如5.7.44),重复你的测试流程,看是否还有缺失情况。
四、慢日志写入的机制问题
虽然你已经确认慢日志有记录,但可能存在异步写入导致的部分记录丢失:
- MySQL的慢日志默认是异步写入的,如果在脚本结束时,缓冲区的日志还没刷到磁盘,就会出现统计偏差
- 日志文件的权限或磁盘空间问题(但你已经有5万多条记录,大概率不是这个原因)
排查方向:
- 在测试结束后,手动执行
FLUSH SLOW LOGS强制刷盘,再统计慢日志的记录数 - 检查慢日志文件的完整性,看是否有截断或损坏的情况(比如用
tail查看最后几条记录是否完整)
五、临时开启General Log做对比
如果上面的方法都没找到原因,可以临时开启General Log(注意:会严重影响性能,仅短时间测试),对比General Log的记录数和Queries、慢日志的差异:
SET GLOBAL general_log = ON; SET GLOBAL general_log_file = '/tmp/general.log';
等待几分钟后关闭,然后统计:
grep 'Query' /tmp/general.log | wc -l
对比这个数值和Queries的差值,再看哪些出现在General Log但没出现在慢日志里,就能定位到具体的缺失语句类型。
内容的提问来源于stack exchange,提问作者Peter V. Mørch
相关产品推荐
相关产品推荐

