当前位置:首页 > 娱乐

如何让数据库监控慢查询

一条SQL跑了12秒,何让接口超时了三次,数据用户投诉到客服。库监控慢登录服务器一看,查询慢查询日志里躺着十几条类似的何让语句,全是数据全表扫描。这不是库监控慢偶发,是查询常态。数据库监控慢查询,何让核心就一件事:让那些拖后腿的数据SQL无处遁形,然后干掉它们。库监控慢

先说抓。查询MySQL有慢查询日志,何让打开它只是数据第一步。很多团队开了日志却从不看,库监控慢文件涨到几个G,真出问题时翻都翻不动。我的习惯是设置long_query_time为1秒,别用默认的10秒——10秒的查询早就把连接池占满了,你监控到的只是尸体。配合pt-query-digest工具每天跑一次分析,把TOP 10的慢SQL推到群里,谁写的谁认领。PostgreSQL这边用pg_stat_statements扩展,按总耗时排序,比单看平均耗时更准,因为一条执行1000次、每次0.5秒的查询,比一条执行1次、耗时3秒的查询危害大得多。

抓到了之后,别急着加索引。我见过太多人一看到慢查询就ALTER TABLE ADD INDEX,结果写性能掉了一半。先看执行计划。EXPLAIN输出里,type=ALL是全表扫描,rows预估行数动辄几十万,Extra里出现Using filesort或Using temporary,这些都是红灯。但红灯未必都要立刻改——如果这张表只有200行数据,全扫就全扫,加索引反而增加写入开销。判断标准是数据量和调用频率的乘积。

有个案例印象很深。一张订单表,联合索引建在(user_id, status, created_at)上,但有个查询条件是WHERE status = 'pending' AND created_at > '2024-01-01',没带user_id。索引最左前缀原则失效,直接全表扫。开发同学说“我建了索引啊”,对,建了但没用上。后来把索引顺序调成(status, created_at, user_id),查询从4.2秒降到0.03秒。索引不是建了就行,顺序决定生死。

监控工具的选择上,别一上来就上Prometheus加Grafana那套。小团队用mysqldumpslow加个crontab就够了,把结果写进一张监控表,用Metabase画个趋势图。大团队可以考虑Percona Monitoring and Management或者Datadog的数据库监控,但核心指标就那几个:慢查询数量、平均响应时间、锁等待时间、扫描行数与返回行数的比值。最后一个指标特别有用——如果扫描10000行只返回10行,说明索引选择性极差,该考虑重构查询或者加覆盖索引了。

还有一点容易忽略:监控慢查询不只是监控SELECT。UPDATE和DELETE的慢查询同样致命,尤其在业务高峰期,一条没走索引的UPDATE可能锁住整张表。我习惯在long_query_time之外,再单独监控innodb_row_lock_time_avg,超过50毫秒就告警。锁等待的连锁反应比单条慢查询可怕得多。

最后说个反直觉的做法。有些慢查询是“合理”的,比如夜间跑批的统计任务,跑30秒无所谓。监控系统要能区分OLTP和OLAP场景,别把报表查询和在线交易混在一起告警。我的做法是给不同业务打标签,在线服务的慢查询阈值设1秒,离线任务设30秒,分开统计。否则每天被无效告警淹没,真正的故障反而被忽略。

监控慢查询这件事,工具只占三成,剩下七成是持续跟进。每周花半小时看慢查询趋势,比买最贵的APM都管用。

分享到: