当前位置: 首页 > article >正文

不上APM,103行代码搞定慢SQL检测:超100毫秒自动入库

不上APM103行代码搞定慢SQL检测超100毫秒自动入库原创于 2026-04-14 06:40:21 发布·更新于 2026-04-14 10:30:00非科班野生程序员深耕政务信息化20年。从VC到PB再到Java自研框架browise也打磨了十几年。最近整理框架代码发现不少有趣的决策——政务内网环境部署APM麻烦重重于是琢磨出一个轻量级慢SQL检测方案103行核心代码无需任何外部监控组件超100毫秒的慢SQL自动入库运维直接查表就能定位优化今天整理优化后版本分享给有同样需求的同行。最后感谢豆包、智谱、OpenCode决策是我做的代码是我搓的文字是他们协助总结优化的。文章标签#sql #数据库 #java #后端 #慢SQL监控 #MyBatis #政务信息化一、场景痛点政务内网无APM慢SQL难定位做政务系统的同行都懂系统上线后偶尔会收到用户反馈“页面卡”“操作响应慢”但排查起来却一头雾水——到底是SQL执行慢、网络延迟还是前端渲染卡顿常规解决方案是上APM应用性能监控但政务内网环境特殊部署APM需要申请权限、配置网络、协调运维整个流程繁琐且耗时往往小问题拖成大麻烦。基于此我想到一个轻量级方案在自研框架层埋点计时捕捉每一条SQL的执行耗时超过设定阈值默认100毫秒的SQL自动记录到数据库专用表中运维人员定期查询该表就能快速定位需要优化的慢SQL无需复杂部署零侵入业务代码。二、优化后核心代码可直接生产使用原代码存在线程不安全、SQL注入风险、资源泄漏、硬编码等问题优化后保留核心逻辑解决所有隐患兼容MyBatis适配政务系统OLTP场景核心代码103行不含注释如下import org.apache.ibatis.mapping.BoundSql;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.session.Configuration;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.springframework.stereotype.Component;import javax.annotation.Resource;import java.sql.Connection;import java.sql.PreparedStatement;import java.sql.SQLException;import java.text.SimpleDateFormat;import java.util.Date;import java.util.Objects;/**轻量级慢SQL监控工具核心功能无需APMSQL执行耗时超100毫秒自动入库适配场景政务内网、无APM部署条件的JavaMyBatis项目核心优势线程安全、防SQL注入、独立事务、零业务侵入/Componentpublic class SlowSqlMonitor {/*慢SQL阈值毫秒可根据业务调整避免硬编码*/private static final long SLOW_SQL_THRESHOLD 100;/**线程安全存储SQL执行开始时间解决多线程并发问题*/private static final ThreadLocal START_TIME_LOCAL new ThreadLocal();/**线程安全存储MyBatis Mapper方法名关联SQL来源*/private static final ThreadLocal METHOD_NAME_LOCAL new ThreadLocal();/**线程安全存储操作类型可选用于区分查询/新增/修改/删除*/private static final ThreadLocal OPER_TYPE_LOCAL new ThreadLocal();Resourceprivate SqlSessionFactory sqlSessionFactory;/**监控开始——SQL执行前调用记录基础信息param methodName Mapper方法全限定名如com.xxx.mapper.UserMapper.selectByIdparam operType 操作类型如SELECT/INSERT/UPDATE/DELETE*/public void startMonitor(String methodName, String operType) {// 记录当前时间作为SQL执行开始时间START_TIME_LOCAL.set(System.currentTimeMillis());// 记录Mapper方法名用于后续解析实际执行SQLMETHOD_NAME_LOCAL.set(methodName);// 记录操作类型便于后续统计分析OPER_TYPE_LOCAL.set(operType);}/**监控结束——SQL执行后调用计算耗时并记录慢SQL*/public void endMonitor() {// 异常捕获确保监控逻辑不影响业务流程try {// 获取线程中存储的基础信息避免空指针Long startTime START_TIME_LOCAL.get();String methodName METHOD_NAME_LOCAL.get();String operType OPER_TYPE_LOCAL.get();if (Objects.isNull(startTime) || Objects.isNull(methodName) || Objects.isNull(operType)) {return;}// 计算SQL执行耗时毫秒 long costTime System.currentTimeMillis() - startTime; // 仅记录超过阈值的慢SQL if (costTime SLOW_SQL_THRESHOLD) { // 解析MyBatis实际执行的SQL包含参数绑定后内容 String executeSql getExecuteSql(methodName); // 独立事务保存慢SQL信息不干扰业务事务 saveSlowSql(methodName, executeSql, operType, costTime); }} catch (Exception e) {// 监控异常不抛出避免影响业务正常执行e.printStackTrace();} finally {// 清理ThreadLocal防止内存泄漏关键优化点START_TIME_LOCAL.remove();METHOD_NAME_LOCAL.remove();OPER_TYPE_LOCAL.remove();}}/**解析MyBatis实际执行的SQL语句param methodName Mapper方法全限定名return 实际执行的SQL过滤特殊字符截取长度适配数据库字段*/private String getExecuteSql(String methodName) {try {// 从MyBatis配置中获取MappedStatement解析真实SQLConfiguration config sqlSessionFactory.getConfiguration();MappedStatement mappedStatement config.getMappedStatement(methodName);BoundSql boundSql mappedStatement.getBoundSql(null);String sql boundSql.getSql();// 过滤单双引号避免拼接SQL时出现注入风险优化点 sql sql.replace(\, ).replace(\, ); // 截取4000字符适配Oracle VARCHAR2字段长度限制 return sql.length() 4000 ? sql.substring(0, 4000) : sql;} catch (Exception e) {// 异常时返回提示不影响整体流程return “SQL解析失败” e.getMessage().substring(0, 100);}}/**独立事务保存慢SQL信息到数据库避免污染业务事务param methodName Mapper方法名param sql 实际执行的SQLparam operType 操作类型param costTime 执行耗时毫秒*/private void saveSlowSql(String methodName, String sql, String operType, long costTime) {// try-with-resources自动关闭资源避免资源泄漏关键优化点try (SqlSession sqlSession sqlSessionFactory.openSession(false);Connection connection sqlSession.getConnection()) {// 使用PreparedStatement彻底避免SQL注入核心优化点 String insertSql INSERT INTO TUNINGEVENT(METHODNAME, SQL, OPER, OPERDATE, ELAPSED) VALUES(?, ?, ?, ?, ?); try (PreparedStatement preparedStatement connection.prepareStatement(insertSql)) { // 绑定参数规范SQL执行 preparedStatement.setString(1, methodName); preparedStatement.setString(2, sql); preparedStatement.setString(3, operType); preparedStatement.setString(4, new SimpleDateFormat(yyyy-MM-dd HH:mm:ss).format(new Date())); preparedStatement.setLong(5, costTime); // 执行插入 preparedStatement.executeUpdate(); // 手动提交事务独立事务不依赖业务事务 connection.commit(); } catch (SQLException e) { // 插入失败回滚不影响业务 connection.rollback(); throw e; }} catch (Exception e) {e.printStackTrace();}}}三、核心设计要点阈值可配置适配不同场景默认阈值设为100毫秒适配政务系统OLTP场景高频、短耗时操作如果是报表查询等耗时场景可直接修改SLOW_SQL_THRESHOLD常量无需修改核心逻辑。相比原代码的硬编码优化后更灵活便于后续维护。线程安全支持高并发原代码使用成员变量存储开始时间、方法名等信息多线程并发时会出现数据混乱。优化后改用ThreadLocal存储每个线程独立存储自己的信息互不干扰同时在endMonitor方法中手动清理ThreadLocal避免内存泄漏适配高并发业务场景。独立事务不干扰业务慢SQL记录采用独立事务通过sqlSessionFactory.openSession(false)开启新的会话手动控制提交和回滚与业务事务完全隔离——即使业务事务回滚慢SQL记录也能正常入库同时避免了原代码中事务递归审计日志触发慢SQL记录的问题。防SQL注入提升安全性原代码采用字符串拼接的方式生成插入SQL存在SQL注入风险。优化后使用PreparedStatement绑定参数彻底杜绝注入问题同时过滤SQL中的单双引号进一步提升安全性适配政务系统对数据安全的高要求。资源安全避免泄漏使用try-with-resources自动关闭SqlSession、Connection、PreparedStatement等资源无需手动关闭避免资源泄漏同时在异常处理中做好兜底确保监控逻辑不会因为资源问题影响业务正常执行。零业务侵入使用简单配合框架AOP使用自定义Monitoring注解标注需要监控的Mapper方法AOP代理会自动在方法执行前后调用startMonitor和endMonitor业务代码无需任何修改完全无感知。记录信息完整便于排查慢SQL信息存入TUNINGEVENT表字段设计清晰便于运维排查和统计具体字段说明如下字段名字段说明备注METHODNAMEMyBatis Mapper方法全限定名快速定位SQL所在位置SQL实际执行的SQL语句过滤引号截取4000字符适配数据库限制OPER操作类型SELECT/INSERT/UPDATE/DELETE便于分类统计OPERDATESQL执行时间格式yyyy-MM-dd HH:mm:ss便于定位时间节点ELAPSEDSQL执行耗时毫秒用于排序快速找到耗时最长的SQLSQL解析优化适配MyBatis通过SqlSessionFactory获取MyBatis配置解析MappedStatement和BoundSql获取参数绑定后的实际执行SQL相比原代码的框架依赖优化后适配主流MyBatis版本通用性更强同时增加异常处理避免SQL解析失败影响整体流程。四、使用方式AOP配置零侵入业务只需两步即可完成部署无需修改业务代码自定义Monitoring注解import java.lang.annotation.*;/**慢SQL监控注解标注在需要监控的Mapper方法上*/Target({ElementType.METHOD})Retention(RetentionPolicy.RUNTIME)Documentedpublic interface Monitoring {// 操作类型默认SELECTString operType() default “SELECT”;}AOP切面配置import org.aspectj.lang.ProceedingJoinPoint;import org.aspectj.lang.annotation.Around;import org.aspectj.lang.annotation.Aspect;import org.springframework.stereotype.Component;import javax.annotation.Resource;/**慢SQL监控AOP切面自动调用监控方法*/AspectComponentpublic class MonitoringAspect {Resourceprivate SlowSqlMonitor slowSqlMonitor;// 环绕通知拦截所有标注Monitoring注解的方法Around(“annotation(monitoring)”)public Object around(ProceedingJoinPoint joinPoint, Monitoring monitoring) throws Throwable {// 获取Mapper方法全限定名包名类名方法名String methodName joinPoint.getSignature().getDeclaringTypeName() “.” joinPoint.getSignature().getName();// 获取注解上的操作类型String operType monitoring.operType();// 开始监控slowSqlMonitor.startMonitor(methodName, operType);try {// 执行业务方法return joinPoint.proceed();} finally {// 无论业务方法是否异常都结束监控并记录慢SQLslowSqlMonitor.endMonitor();}}}表结构创建Oracle示例创建TUNINGEVENT表用于存储慢SQL信息适配代码中的字段设计CREATE TABLE TUNINGEVENT (ID NUMBER(19) PRIMARY KEY AUTO_INCREMENT, – 主键自增METHODNAME VARCHAR2(255) NOT NULL, – Mapper方法名SQL VARCHAR2(4000) NOT NULL, – 执行的SQL语句OPER VARCHAR2(20) NOT NULL, – 操作类型OPERDATE DATE NOT NULL, – 执行时间ELAPSED NUMBER(10) NOT NULL – 执行耗时毫秒);– 索引优化提升查询效率根据ELAPSED排序查询CREATE INDEX IDX_TUNINGEVENT_ELAPSED ON TUNINGEVENT(ELAPSED DESC);五、实际效果与小结这个优化版的慢SQL监控工具核心代码仅103行无需引入任何外部监控组件部署简单、零业务侵入完美适配政务内网环境。我在自己负责的政务系统中上线后第一次查询TUNINGEVENT表就发现了一个跑了8秒的报表查询SQL——由于未加索引导致全表扫描添加索引后执行耗时直接降到200毫秒以内用户反馈的“页面卡”问题彻底解决。相比APM的复杂部署这个轻量级方案更适合中小项目、内网项目运维人员只需定期执行如下查询语句就能快速定位需要优化的慢SQL– 查询耗时前10的慢SQL按耗时降序排列SELECT * FROM TUNINGEVENT ORDER BY ELAPSED DESC LIMIT 10;小结一下核心优势轻量无依赖无需APM103行核心代码部署简单安全可靠线程安全、防SQL注入、资源自动释放零侵入AOP注解不修改业务代码易维护阈值可配置、记录信息完整、排查便捷轻量级SQL监控大家都是怎么做的有没有更好的优化思路欢迎评论区交流探讨~标签#Java #慢SQL #性能监控 #MyBatis #政务信息化 #自研框架 #轻量级监控

相关文章:

不上APM,103行代码搞定慢SQL检测:超100毫秒自动入库

不上APM,103行代码搞定慢SQL检测:超100毫秒自动入库 原创于 2026-04-14 06:40:21 发布更新于 2026-04-14 10:30:00 非科班野生程序员,深耕政务信息化20年。从VC到PB再到Java,自研框架browise也打磨了十几年。最近整理框架代码&…...

Wan2.2-I2V-A14B项目实战:从零搭建个人AI艺术画廊网站

Wan2.2-I2V-A14B项目实战:从零搭建个人AI艺术画廊网站 1. 项目概述与价值 想象一下,你可以在自己的网站上展示由AI生成的独特艺术作品,让访客欣赏、点赞甚至参与创作。这正是我们将要实现的个人AI艺术画廊网站。这个项目不仅能让你的创意作…...

保姆级教程:用Wan2.2-I2V-A14B镜像,RTX4090D快速部署AI视频生成

保姆级教程:用Wan2.2-I2V-A14B镜像,RTX4090D快速部署AI视频生成 1. 准备工作与环境检查 1.1 硬件与系统要求 在开始部署前,请确保您的设备满足以下最低配置要求: 显卡:NVIDIA RTX 4090D 24GB显存(必须匹…...

CRC校验:Modbus数据帧的“指纹”

短文标题:CRC校验:Modbus数据帧的“指纹”【传播知识 手有余香🌹】转发此文到朋友圈 赠送 于振南老师 知识视频合集哦!你有没有想过一个问题:Modbus-RTU数据帧传输时,可能受干扰出错。接收方怎么知道数据有…...

Pixel Epic · Wisdom Terminal 快速入门:Visual Studio开发环境下的首次调用

Pixel Epic Wisdom Terminal 快速入门:Visual Studio开发环境下的首次调用 1. 准备工作 在开始之前,我们需要确保开发环境已经准备就绪。如果你已经安装了Visual Studio,可以跳过安装步骤。 1.1 Visual Studio安装 对于还没有安装Visual…...

视频转PPT终极指南:三分钟从视频中智能提取幻灯片内容

视频转PPT终极指南:三分钟从视频中智能提取幻灯片内容 【免费下载链接】extract-video-ppt extract the ppt in the video 项目地址: https://gitcode.com/gh_mirrors/ex/extract-video-ppt 你是否曾经面对长达数小时的会议录像或教学视频,却需要…...

Realistic Vision V5.1 智能体集成初探:构建具备图像生成能力的Skills智能体

Realistic Vision V5.1 智能体集成初探:构建具备图像生成能力的Skills智能体 最近和几个做创意设计的朋友聊天,他们总在抱怨一个事儿:脑子里有个特别酷的画面,但要么自己手绘不出来,要么找设计师沟通成本太高&#xf…...

openclaw 异常之 increase agents.defaults.timeoutSeconds in your config.

目录 异常回复 openclaw日志 ollama日志 解决方法 异常回复 openclaw 调用本地 ollama 模型进行 cpu 推理时遇到如下回复 Request timed out before a response was generated. Please try again, or increase agents.defaults.timeoutSeconds in your config. openclaw日…...

Spring_couplet_generation 开发环境搭建:IntelliJ IDEA高效开发配置

Spring_couplet_generation 开发环境搭建:IntelliJ IDEA高效开发配置 如果你正在用IntelliJ IDEA做Python开发,特别是想跑通像Spring_couplet_generation这样的AI项目,可能会觉得配置起来有点麻烦。项目依赖多,环境复杂&#xff…...

亲测鹿城热门短视频公司推广效果

在当今数字化时代,短视频运营拍摄行业发展迅猛,但也面临着诸多挑战。浙江一企办企业服务有限公司作为该领域的重要参与者,其技术方案和应用效果值得深入探究。行业痛点分析当前,短视频运营拍摄领域存在着一些技术挑战。行业同质化…...

Redis 大 Key 和热 Key 怎么分别治理?一次讲清识别方式、风险差异与实战处理思路

Redis 大 Key 和热 Key 怎么分别治理?一次讲清识别方式、风险差异与实战处理思路 大家好,我是一名有 4 年工作经验的 Java 后端开发。 Redis 在线上问题里,有两个词经常被一起提到:大 Key 和热 Key。 但很多人其实会把它们混着理解…...

Scroll Reverser:彻底解决Mac多设备滚动冲突的终极方案

Scroll Reverser:彻底解决Mac多设备滚动冲突的终极方案 【免费下载链接】Scroll-Reverser Per-device scrolling prefs on macOS. 项目地址: https://gitcode.com/gh_mirrors/sc/Scroll-Reverser 你是否曾经在MacBook上使用触控板时习惯自然滚动(…...

Qwen3.5-35B-AWQ-4bit多模态落地:跨境电商多语言商品图理解与本地化文案生成

Qwen3.5-35B-AWQ-4bit多模态落地:跨境电商多语言商品图理解与本地化文案生成 1. 跨境电商面临的挑战与解决方案 跨境电商企业每天需要处理大量商品图片和多语言文案工作。传统方式需要人工查看图片内容,再用不同语言撰写商品描述,效率低下且…...

HY-Motion 1.0部署避坑指南:快速启动Gradio可视化界面

HY-Motion 1.0部署避坑指南:快速启动Gradio可视化界面 1. 引言:从兴奋到困惑,只差一个启动命令 当你看到HY-Motion 1.0的介绍时,是不是和我一样兴奋?一个能通过文字描述直接生成3D人体动画的工具,听起来就…...

千问3.5-2B智能运维助手:自动化日志分析与故障排查

千问3.5-2B智能运维助手:自动化日志分析与故障排查 1. 运维工作的痛点与挑战 运维工程师每天都要面对海量的服务器日志和监控数据,传统的人工排查方式已经难以应对现代分布式系统的复杂性。想象一下凌晨3点被报警电话惊醒,面对几十GB的日志…...

OBS多平台直播插件完整指南:obs-multi-rtmp实现一键多平台推流

OBS多平台直播插件完整指南:obs-multi-rtmp实现一键多平台推流 【免费下载链接】obs-multi-rtmp OBS複数サイト同時配信プラグイン 项目地址: https://gitcode.com/gh_mirrors/ob/obs-multi-rtmp 你是否曾为每次直播只能选择一个平台而烦恼?想要同…...

影墨·今颜小红书人像生成指南:3步打造电影质感东方写真

影墨今颜小红书人像生成指南:3步打造电影质感东方写真 "以泼墨之势,绘当代之影。" 你是否也曾被那些充满电影质感的小红书人像照片所吸引?那些光影交错、细节丰富、充满东方韵味的作品,现在通过「影墨今颜」AI影像系统&…...

Laravel 7.x 核心特性全解析

好的,Laravel 7.x 引入了多项重要的新特性和改进,主要集中在提升开发效率、增强路由功能、改进测试工具等方面。以下是其主要特性概述:路由模型绑定增强自定义键名:在路由定义中,除了 id,现在可以明确指定模…...

负载箱的选型方法论与系统集成:从需求分析到全生命周期决策

引言在负载箱的技术讨论中,大量篇幅聚焦于设备本身的原理、设计和制造。然而,对于负载箱的用户而言,一个更为前置和关键的问题是:面对市场上数百种规格各异的产品,如何选择最适配的型号?如何将一台负载箱无…...

通义千问2.5-7B本地部署实战:4GB显存低成本运行方案

通义千问2.5-7B本地部署实战:4GB显存低成本运行方案 1. 引言 在AI大模型应用日益普及的今天,如何在有限的硬件资源上高效运行中等规模语言模型成为许多开发者和企业关注的重点。通义千问2.5-7B-Instruct作为阿里云最新发布的70亿参数指令微调模型&…...

终极WeMod专业版免费解锁指南:Wand-Enhancer完整教程

终极WeMod专业版免费解锁指南:Wand-Enhancer完整教程 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 想要免费解锁WeMod专业版的所有高级功能…...

Cortex-A7 MPCore 架构

鉴于学习的硬件使用的是Cortex-A7架构,本章学习该架构的相关知识。了解了 Cortex-A7 架构以后有利于我们后面的学习,因为后面有很多例程涉及到 Cortex-A7 架构方面的知识,比如处理器模型、 Cortex-A7 寄存器组等等。Cortex-A7 MPCore 简介Cor…...

Llama-3.2-3B新手入门:用Ollama一键搭建你的本地AI助手

Llama-3.2-3B新手入门:用Ollama一键搭建你的本地AI助手 1. 为什么选择Llama-3.2-3B和Ollama组合 1.1 轻量级但实用的AI助手 Llama-3.2-3B是Meta最新推出的30亿参数语言模型,专为日常对话和多语言理解优化。相比其他同规模模型,它有三个突出…...

《机电安装行业数字化转型样板:陕西高信项目管理系统试运行报告》

背景:没有系统之前,客户反馈是怎么管项目的?在引入项目管理系统之前,陕西高信(能源)机电厂机电安装项目的管理方式,可以用四个字概括——“人治纸治”。表面上看,项目有预算、有计划…...

【奇点2026权威发布】:AIAgent任务调度必须绕开的7个LLM原生缺陷(附可验证的调度补偿算法伪代码)

第一章:【奇点2026权威发布】:AIAgent任务调度必须绕开的7个LLM原生缺陷(附可验证的调度补偿算法伪代码) 2026奇点智能技术大会(https://ml-summit.org) 大型语言模型在AIAgent任务调度中并非“即插即用”的可靠执行引擎——其底…...

Kandinsky-5.0-I2V-Lite-5s入门必看:PyCharm中调试模型调用代码详解

Kandinsky-5.0-I2V-Lite-5s入门必看:PyCharm中调试模型调用代码详解 1. 准备工作与环境配置 在开始调试Kandinsky-5.0-I2V-Lite-5s模型之前,我们需要确保开发环境已经正确设置。PyCharm作为一款强大的Python IDE,能够显著提升我们的开发效率…...

亲测机电一体化系统维保品牌实践分享

在工业生产和日常生活中,机电一体化系统的稳定运行至关重要,而其维保工作更是保障系统性能的关键。近期我对众逸联机电一体化系统维保服务进行了亲测,下面为大家分享实践体验。直击行业痛点机电一体化系统维保领域存在诸多痛点。行业报告显示…...

AIAgent目标分解实战手册(工业级SOP首次公开):从模糊意图到可执行子任务的7步原子化流程

第一章:目标分解在AIAgent架构中的核心定位与演进脉络 2026奇点智能技术大会(https://ml-summit.org) 目标分解是AIAgent实现复杂任务自主执行的逻辑基石,它将高层语义目标(如“为用户规划一次低碳商务差旅”)逐层拆解为可调度、…...

音视频处理框架

音视频处理框架:数字时代的核心技术引擎 在数字化浪潮中,音视频内容已成为信息传递的核心载体,而音视频处理框架则是支撑这一领域的底层技术基石。无论是短视频平台的实时滤镜、在线会议的降噪功能,还是影视作品的后期剪辑&#…...

FPGA开发者必看:UltraScale Plus中URAM与BRAM的5大实战区别(附配置示例)

FPGA开发者必看:UltraScale Plus中URAM与BRAM的5大实战区别(附配置示例) 在UltraScale Plus系列FPGA的设计中,存储资源的高效利用往往是项目成败的关键。作为硬件工程师,我们常常需要在BRAM和URAM之间做出选择——这两…...