MySQL预编译语句过多告警排查及解决方案

 更新时间:2025年01月26日 10:18:19   作者:MrCao杰罗尔德  
在使用Spring Cloud Alibaba搭建的微服务架构中,项目采用ShardingSphere进行分库分表,MyBatis-Plus作为持久层,线上环境突发大量预编译语句过多的数据库告警,导致系统性能下降,所以本文给大家介绍了MySQL预编译语句过多告警排查及解决方案,需要的朋友可以参考下

业务背景

在使用Spring Cloud Alibaba搭建的微服务架构中,项目采用ShardingSphere进行分库分表,MyBatis-Plus作为持久层。线上环境突发大量预编译语句过多的数据库告警,导致系统性能下降。

排查过程

1. 初步排查:联系云数据库厂商

首先,联系云数据库服务厂商协助排查,确认问题是由于预编译缓存未被释放,导致占用过多数据库资源。

2. 排查连接池配置

怀疑问题与连接池有关,特别是考虑到线上负载较高的高峰时段。经过检查,项目使用的是HikariCP连接池,相关配置如下:

特别关注两个参数:

  • maxLifetime: 连接池最大生命周期
  • idleTimeout: 连接池空闲超时时间

在进行断点调试后,由于项目使用了Sharding-JDBC,某些参数并未按照Hikari的默认值生效,而是被Sharding进行初始化配置。Sharding的相关代码如下:

此时可以初步排除连接池配置问题,因为Sharding已将idleTimeout配置为60秒。

3. 分析HikariCP源码与Statement Cache问题

深入分析HikariCP源码,查找与PreparedStatement缓存相关的内容,发现README.md关键描述:

Statement Cache

HikariCP与其他连接池(如Apache DBCP、Vibur、c3p0等)在处理PreparedStatement缓存时的区别:

  • HikariCP: 不提供PreparedStatement缓存,原因是连接池层级缓存PreparedStatement只能按连接缓存,导致内存占用过大。
  • 其他连接池: 许多连接池提供PreparedStatement缓存,但这会导致大量PreparedStatement对象及相关执行计划在内存中存储,影响性能。

HikariCP并不缓存PreparedStatement,因为多数数据库JDBC驱动已经内置缓存机制,可以跨连接共享执行计划,避免重复占用内存。

要点:

  • 连接池层级的PreparedStatement缓存问题:在连接池层缓存会导致大量内存占用,且不支持跨连接共享。
  • 数据库驱动缓存的优势:数据库驱动层提供的缓存更高效,能够共享执行计划,减少内存占用。
  • 反模式:在连接池层进行缓存PreparedStatement是性能反模式。

4. MySQL驱动配置分析

进一步排查MySQL驱动,发现项目使用的mysql-connector-j:8.3.0驱动,关键配置useServerPrepStmts默认为true,即开启服务端的预编译缓存。而在同一项目中,其他服务使用的是mysql-connector-java:8.0.16,该版本的默认配置为false。

核心代码:

通过对比,确认开启服务端预编译缓存是导致告警的根本原因。

解决方案

通过排查,最终确定问题原因是服务端的预编译缓存未关闭。由于项目采用分库分表,并且在同一数据库实例中创建了多个Schema,默认开启的服务端预编译缓存容易导致资源占用过高。

解决步骤:

在JDBC连接字符串中添加配置&useServerPrepStmts=false,关闭MySQL的服务端预编译缓存。

例如,JDBC连接URL修改如下:

jdbc:mysql://localhost:3306/dbname?useServerPrepStmts=false

配置完成后,重新启动服务,观察效果。关闭服务端预编译缓存后,数据库告警明显减少,系统性能得到提升。

总结

通过排查,我们确认了预编译语句过多告警的根本原因是MySQL服务端开启了预编译缓存,导致过多的执行计划占用资源。解决方案是关闭服务端的PreparedStatement缓存,减少系统负载并提升性能。

到此这篇关于MySQL预编译语句过多告警排查及解决方案的文章就介绍到这了,更多相关MySQL预编译语句过多告警内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 聊聊MySQL中的参数

    聊聊MySQL中的参数

    这篇文章主要介绍了MySQL中的参数是什么,帮助大家更好的理解和使用MySQL数据库,感兴趣的朋友可以了解下
    2020-09-09
  • Mysql无法选取非聚合列的解决方法

    Mysql无法选取非聚合列的解决方法

    这篇文章主要给大家介绍了关于Mysql无法选取非聚合列的解决方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-09-09
  • phpstudy安装后mysql无法启动的解决

    phpstudy安装后mysql无法启动的解决

    本文主要介绍了phpstudy安装后mysql无法启动的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-03-03
  • MySql增加用户、授权、修改密码等语句

    MySql增加用户、授权、修改密码等语句

    MySql 新建用户,新建数据库,用户授权,删除用户,修改密码
    2008-09-09
  • 关于MySQL中“Insert into select“ 的死锁情况分析

    关于MySQL中“Insert into select“ 的死锁情况分析

    这篇文章主要介绍了关于MySQL中“Insert into select“ 的死锁情况分析,死锁是指两个或者多个事务在同一资源上的相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象,需要的朋友可以参考下
    2023-05-05
  • MySQL删除数据库的两种方法

    MySQL删除数据库的两种方法

    这篇文章主要为大家详细介绍了MySQL删除数据库的两种方法,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • Mysql select in 按id排序实现方法

    Mysql select in 按id排序实现方法

    有时候我们在后台选择了一系列的id,我们想安装填写id的顺序进行排序,那么就需要下面的order by方法,测试通过
    2013-03-03
  • mysql免安装版配置步骤详解分享

    mysql免安装版配置步骤详解分享

    这篇文章主要介绍了mysql免安装版配置步骤详解,提供了二个网友的安装方法,大家可以参考使用
    2013-12-12
  • Mysql索引结合explain分析示例

    Mysql索引结合explain分析示例

    本文主要介绍了Mysql索引结合explain分析示例,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-02-02
  • 查看修改MySQL表结构命令

    查看修改MySQL表结构命令

    这篇文章主要介绍了查看修改MySQL表结构命令,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-12-12

最新评论