数据库又慢了?你需要一个像样的慢SQL报警系统

关注我的公众号:【编程朝花夕拾】,可获取首发内容。

01 引言

在当今数据驱动的时代,数据库是任何应用系统的核心。而慢SQL,则是数据库最怕又最常见的问题。它悄然滋生,初期难以察觉,但一旦爆发,便会导致应用响应迟缓、系统资源耗尽,甚至引发服务雪崩。

因此,一个设计良好的慢SQL报警系统,不再是可选项,而是保障系统稳定性和用户体验的生命线。

02 契机

前两天帮同事排查一个问题,线下都是好好的,一到生产环境,代码卡死,最后通过Arthas工具才发现,是因为慢SQL导致的,耗时大概1分钟左右。真的是吃了大亏了。

但是,当时的大坑就是因为慢SQL导致客户端超时超时,拿到的数据结果为空,从而报空指针异常,被空指针直接误导带偏。

Arthas虽然可以采集结果,但也只是全部执行完成之后才会打印信息。慢SQL会直接将信息阻塞,给人的错觉就是没有执行到监控的地方。

于是想,如果SQL执行完执行时间超过某个阈值,自动推送消息,就可以快速定位到问题了。带着这个问题,我们开启今天的文章介绍。

03 Mysql自带的参数

Mysql本身支持慢SQL的监控,会将超过阈值的SQL保存到执行的位置。关键参数如下:

  • slow_query_log:开启慢SQL日志的开关(ON/OFF)
  • slow_query_log_file:慢SQL存放的位置
  • long_query_time:阈值,单位秒(s)

3.1 设置命令

这些参数可以在Mysql的配置文件里面修改,也可以通过命令修改。我们先通过命令查看:

sh 复制代码
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'slow_query_log_file';
SHOW VARIABLES LIKE 'long_query_time';

3.2 监控文件

我们通过SHOW VARIABLES LIKE 'slow_query_log_file'找到慢SQL的位置,通过命令可以追踪日志:

sh 复制代码
tail -f /data/log/slow.log

当有慢SQL超过阈值会自动将信息写入文件。

3.3 日志采集

文件监控到了,但是并不能主动报警,我们需要采集日志数据然后分析报警。日志的采集工具有很多如:FilebeatLogStashFloume等。

关于日志采集我们会后期会专门用一期讲,这里就不在赘述!

04 Mybaits拦截器监控

Mybaits拦截器不仅能够打印SQL,当然还可以监听SQL执行的时间。这个需要我们自己去实现,灵活度更好,不需要任何第三方的插件。

4.1 拦截器案例

java 复制代码
@Intercepts({
        @Signature(type = StatementHandler.class, method = "query", args = {Statement.class, ResultHandler.class}),
        @Signature(type = StatementHandler.class, method = "update", args = {Statement.class})
})
@Component
public class SqlExcuteTimeInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        StopWatch watch = new StopWatch("SqlExcuteTimeInterceptor");
        watch.start();
        Object proceed = invocation.proceed();
        watch.stop();

        // 打印SQL
        StatementHandler handler = (StatementHandler) invocation.getTarget();
        BoundSql boundSql = handler.getBoundSql();
        // 获取原始SQL
        String sql = boundSql.getSql();
        Object param = boundSql.getParameterObject();

        // 美化SQL输出
        System.out.println("\n=============== SQL日志 ===============");
        System.out.println("原始SQL:" + sql);
        System.out.println("SQL: " + sql.replaceAll("\\s+", " ").trim());
        System.out.println("参数: " + JSON.toJSONString(param));
        System.out.println("执行SQL耗时: " + watch.getTotalTimeMillis() + "ms");
        System.out.println("=========================================");
        return proceed;
    }
}

我们的拦截器中进行了执行时间的计算以及SQL的打印。要注意的是,我们的拦截器针对queryupdate方法进行了拦截。

4.2 实现效果

这里的效果只是将结果打印出来。实际应用中,需要根据执行的时间和配置阈值校验,最后推送给负责人。可以通过企业微信、钉钉、微信、手机短信等工具。

05 小结

其实很多三方工具(如SkyWalking等)已经集成了SQL的报警,尤其云厂商。只需要配置对应的报警方式即可。但是针对一些小微企业,类似拦截器这样的实现更能满足个性的话需求,最重要的节省成本。

而我们要做的就是设计好慢SQL的报警,要设计一个慢SQL报警系统,本质上是在构建一个"数据库性能风险的早期预警系统"。它要求我们不仅是技术的堆砌,更是对数据库性能管理的深刻理解。

从一个简单的日志收集器,到一个具备智能分析、精准报警和闭环治理能力的平台,每一步进化都将为业务的稳定和高效运行注入更强的韧性。投资这样一个系统,就是投资系统的未来。

相关推荐
唐叔在学习2 小时前
听说有老哥分不清Git branch和tag?这不看看嘛
git·后端
听风同学2 小时前
向量数据库---Chroma数据库入门到进阶教程
后端·架构
法欧特斯卡雷特2 小时前
Kotlin 2.2.20 现已发布!下个版本的特性抢先看!
android·前端·后端
Reboot2 小时前
寒武纪显卡命令
后端
码事漫谈2 小时前
为什么C++多态必须使用指针或引用?——从内存布局和对象身份的角度深入解析
后端
风一样的树懒2 小时前
如何建高可用系统:接口限流
后端
Reboot2 小时前
内网IDEA集成离线版DeepSeek指南
后端
xhbh6662 小时前
MySQL数据导出避坑指南:如何选择正确的工具并设计安全的备份策略?
数据库·mysql·oracle·程序员·mysql导出数据库
惜鸟2 小时前
Python中@classmethod与@staticmethod区别
后端