数据库又慢了?你需要一个像样的慢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报警系统,本质上是在构建一个"数据库性能风险的早期预警系统"。它要求我们不仅是技术的堆砌,更是对数据库性能管理的深刻理解。

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

相关推荐
2501_933923256 分钟前
Spring Bean作用域揭秘:单例、原型、请求与会话的区别
java·后端·spring·java-ee
学编程就要猛23 分钟前
基于Spring AI 的智能聊天机器人
java·spring ai·chat robot
修炼室25 分钟前
Java开发工程师笔试经验贴【高频知识】
java
木井巳38 分钟前
【记忆化搜索】最长递增子序列
java·算法·leetcode·深度优先·剪枝·推荐算法
一拳不是超人43 分钟前
做独立开发三个月,我的第一个产品终于有了 1000 个用户
前端·程序员
杨杨杨大侠1 小时前
知识库已经有了,Java 程序员还要做什么?Spring AI RAG 实战
java·openai·ai编程
高级程序源1 小时前
django招聘网站信息爬取与分析系统79704-计算机课程设计、毕业设计
后端·python·mysql·小程序·django·flask·课程设计
伊信1 小时前
Spring AI 基础学习与应用
java·后端
夜郎king1 小时前
基于 Java + Playwright 实现网站自动访问与数据采集(以腾讯云开发者社区为例)
java·playwright·网页数据获取
Anastasiozzzz1 小时前
重新定义 Agent 基建:Redis 在现代 AI 与智能体系统中的工程实践
java·人工智能·redis·ai