You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

MariaDB慢查询日志返回行数不符、元数据锁阻塞及max_statement_time无杀进程记录问题排查

MariaDB慢查询日志返回行数不符、元数据锁阻塞及max_statement_time无杀进程记录问题排查

我来帮你逐个拆解和分析你遇到的这几个问题:

一、慢查询日志Rows_sent与实际返回行数不符的原因

你提到正常查询返回1756行,但慢查询日志里Rows_sent只有48,这不是你理解错了——这个字段的实际含义是查询被中断前已经发送给客户端的行数,而非查询最终应该返回的总行数。

结合你的场景,这个长查询大概率是在执行过程中被意外中断了(比如手动kill、触发max_statement_time超时,或是因为元数据锁阻塞导致执行停滞),所以只来得及返回48行就停止了。再看你的EXPLAIN结果,查询走了主键索引,预估行数73、过滤率100%,说明正常情况下这个查询应该很快,不会出现全表扫描的问题,随机变慢的根源不在索引或查询本身,而是锁或并发冲突。

二、"Waiting for table metadata lock"阻塞的排查思路

大量会话卡在这个状态,手动kill可疑查询就恢复,说明有会话持有了表的元数据锁,导致其他访问该表的请求排队等待。常见原因和排查方法:

  • 检查未提交的长事务:执行SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX查看当前活跃事务,找到trx_started时间很久的事务,对应的trx_mysql_thread_id就是持有锁的会话ID,杀掉它就能释放锁。
  • 排查DDL操作冲突:如果有定时的ALTER TABLEOPTIMIZE TABLE等操作,这些操作会申请表的元数据锁;正在运行的长查询会阻塞DDL,后续的其他查询又会等待DDL的锁,形成连锁阻塞。可以检查数据库的定时任务或运维操作记录。
  • 查看锁详情:执行SHOW ENGINE INNODB STATUS,在TRANSACTIONS部分可以看到当前的锁等待关系,明确是谁在持有锁、谁在等待。

三、max_statement_time杀死查询无记录的解决方法

MariaDB 10.6默认不会把被max_statement_time终止的查询记录到error.log,你需要开启专门的日志参数:

  1. 在配置文件(比如my.cnf)中添加:
    log_statement_terminate = ON
    
  2. 重启MariaDB或者执行SET GLOBAL log_statement_terminate = ON;(临时生效,重启后失效)
    开启后,被终止的查询会被记录到error.log里,格式类似:[Note] Query terminated by max_statement_time: ...

另外,你也可以通过performance_schema.events_statements_history表查看最近被终止的查询记录,不过需要确保performance_schema是开启状态。

一些额外的优化建议

  1. 给业务查询设置合理的max_statement_time阈值,避免单个查询长时间占用资源。
  2. 调整innodb_lock_wait_timeout(默认50秒),如果是行锁等待,超时后会自动释放,避免会话无限期等待。
  3. 监控长事务,比如设置long_query_time的同时,也监控未提交的事务时长,及时清理僵死会话。

备注:内容来源于stack exchange,提问作者ragul rangarajan

火山引擎 最新活动