mybatis性能监控应优先拦截executor的query和update方法:覆盖全sql类型,可直接获取mappedstatement、完整sql与参数,耗时统计包含事务和缓存开销,稳定性优于statementhandler;需用system.nanotime()精准计时、finally块保障异常记录、设阈值告警,并支持脱敏、结果集统计与异步上报。

MyBatis 配置 Interceptor 实现 SQL 性能拦截,核心是通过插件机制在 Executor 或 StatementHandler 层统一拦截执行过程,记录耗时、提取 SQL、判断超时,全程不改业务代码。
选对拦截点:Executor 还是 StatementHandler?
性能监控推荐优先拦截 Executor 接口的 query 和 update 方法:
- 覆盖所有增删改查操作(SELECT/INSERT/UPDATE/DELETE)
- 可直接获取
MappedStatement,拿到 SQL ID、完整 SQL、参数对象 - 执行耗时统计更贴近真实数据库响应时间(含事务、缓存等开销)
- 比 StatementHandler 更稳定——后者在某些动态 SQL 场景下可能因代理嵌套导致
getBoundSql()异常
写一个轻量级性能拦截器
实现 Interceptor 接口,用 @Intercepts 注解声明拦截目标:
- 在
intercept()中用System.nanoTime()计时(比currentTimeMillis()更精准) - 从
invocation.getArgs()[0]取出MappedStatement,调用getBoundSql(param)获取最终 SQL - 设置阈值(如 500ms),超时则用 warn 级别输出 SQL ID 和耗时
- 务必放在
finally块中统计,确保异常时也能记录
注册到 MyBatis 配置中
Spring Boot 项目中,在配置类里将拦截器加入 SqlSessionFactoryBean:
- 新建拦截器 Bean(如
PerformanceInterceptor) - 调用
sqlSessionFactoryBean.setPlugins(new Interceptor[]{performanceInterceptor}) - 非 Spring 环境则在
mybatis-config.xml的<plugins></plugins>标签内声明 - 可配合
setProperties()加载外部配置(如阈值、是否启用),提升灵活性
增强实用性的小技巧
让拦截器不止于“打日志”:
- 对 SQL 做简单脱敏:把
WHERE phone = '138****1234'替换为占位符,避免敏感信息泄露 - 统计结果集大小:
result != null && result instanceof Collection时记录 size - 结合线程上下文(如 TraceId)输出,方便链路追踪对齐
- 异步上报:把慢 SQL 信息发到 Kafka 或内存队列,避免阻塞主流程











