You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MySQL升级至8版本后Java应用出现数据库连接过多问题

MySQL 8升级后Java应用数据库连接过多问题排查与解决

问题背景

原使用MySQL 5,升级至MySQL 8后,部署在Tomcat上的Java应用无法正常运行。更新pom.xml中的MySQL依赖后应用可启动,但出现too many connection错误。执行SHOW PROCESSLIST查询后,发现约200条user1的连接记录,且MySQL已设置max_connexion=200。

依赖更新情况

更新前pom.xml依赖:

<dependency>
    <groupId>org.mariadb.jdbc</groupId>
    <artifactId>mariadb-java-client</artifactId>
    <version>1.7.3</version>
</dependency>

<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
</dependency>

更新后pom.xml依赖:

<dependency>
   <groupId>org.mariadb.jdbc</groupId>
   <artifactId>mariadb-java-client</artifactId>
   <version>1.8.0</version>
</dependency>
<dependency>
   <groupId>com.mysql</groupId>
   <artifactId>mysql-connector-j</artifactId>
   <version>8.0.33</version>
</dependency>

相关配置文件

persistence.xml配置(关联database1)

<properties>
        
            <property name="hibernate.connection.driver_class" value="org.mariadb.jdbc.Driver" />
            <property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
            <property name="hibernate.cache.use_second_level_cache" value="true" />
            <property name="hibernate.cache.use_query_cache" value="true" />
            <property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory"/>
            <property name="hibernate.cache.provider_class"  value="org.hibernate.cache.EhCacheProvider"  />
            <property name="hibernate.show_sql" value="false" />
            <property name="hibernate.format_sql" value="false" />
            <property name="hibernate.generate_statistics" value="true" />
            <property name="hibernate.connection.release_mode" value="auto" />
            <property name="hibernate.archive.autodetection" value="class, hbm"/>
            <property name="hibernate.bytecode.use_reflection_optimizer" value="true"/>
            <property name="hibernate.bytecode.provider" value="javassist"/>


            <!-- create database schema at startup -->
            <!-- not for real application -->
            <!-- <property name="hibernate.hbm2ddl.auto" value="create" /> -->


            <property name="connection.provider_class"  value="org.hibernate.connection.C3P0ConnectionProvider"/>
            <property name="hibernate.c3p0.min_size" value="5" />
            <property name="hibernate.c3p0.max_size" value="20" />
            <property name="hibernate.c3p0.timeout" value="3600" /> <!-- <property name="hibernate.c3p0.timeout" value="1800" /> -->
            <property name="hibernate.c3p0.idle_test_period" value="3600"/> <!-- idle_test_period < timeout -->
            <property name="hibernate.c3p0.max_statements" value="50" />
            <property name="hibernate.c3p0.preferredTestQuery" value="SELECT 1" />
            <property name="hibernate.c3p0.testConnectionOnCheckin" value="true" />
            <property name="hibernate.c3p0.testConnectionOnCheckout" value="false" /> <!-- pas recommandé : http://www.mchange.com/projects/c3p0/ --><!-- <property name="c3p0.testConnectionOnCheckout" value="true" /> -->
 
             <property name="hibernate.connection.url" value="jdbc:mysql://${serverNameBD}:${portNumberBD}/${databaseNameBD}"/>
             <property name="hibernate.connection.driver_class" value="org.mariadb.jdbc.Driver" />
             <property name="hibernate.connection.password" value="${passwordBD}" />
              <property name="hibernate.connection.username" value="${userBD}" />


            <property name="hibernate.connection.autoReconnect" value="true" />
            <property name="hibernate.connection.autoReconnectForPools" value="true" />
            <property name="hibernate.connection.is-connection-validation-required" value="true" />


</properties>

hibernate.properties配置(关联database100)

hibernate.connection.driver_class=com.mysql.jdbc.Driver
hibernate.connection.url=jdbc:mysql://ip:3306/database100(not database1)
hibernate.connection.username=user1
hibernate.connection.password=passwrod
hibernate.dialect=org.hibernate.dialect.MySQLInnoDBDialect
hibernate.show_sql=true
jpa.dialect=org.springframework.orm.jpa.vendor.HibernateJpaDialect
jpa.vendor.adapter=HibernateJpaVendorAdapter

问题分析

  • 多配置文件冲突:同时存在persistence.xml和hibernate.properties,可能导致Hibernate初始化多个连接池,总连接数直接打满MySQL的连接上限。
  • 驱动类适配问题:MySQL 8要求使用com.mysql.cj.jdbc.Driver,当前配置混用MariaDB驱动和旧版MySQL驱动,可能引发连接管理异常。
  • 连接池参数不合理:C3P0的空闲超时和检测周期设置过长(1小时),导致空闲连接长期占用资源;若存在多个连接池实例,总连接数极易超标。
  • 代码连接泄漏:如果业务代码中未正确关闭EntityManager/Session,会导致连接持续占用,最终耗尽所有连接。

解决方案

1. 统一配置文件,消除冲突

保留persistence.xml或hibernate.properties其中一个,删除另一个:

  • 若保留persistence.xml,将所有数据库、连接池配置集中至此,确保没有重复配置;
  • 若保留hibernate.properties,移除persistence.xml中的连接相关配置,避免重复加载。

2. 修正驱动类适配MySQL 8

  • 使用MySQL官方驱动时,将驱动类改为com.mysql.cj.jdbc.Driver;
  • 使用MariaDB驱动时,升级到兼容MySQL 8的稳定版本(如3.3.3),同时调整JDBC URL添加必需参数:
    jdbc:mysql://${serverNameBD}:${portNumberBD}/${databaseNameBD}?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
    

3. 优化连接池参数

调整C3P0配置,缩短空闲连接生命周期,控制单池连接数:

<property name="hibernate.c3p0.min_size" value="2" /> <!-- 降低最小空闲连接数 -->
<property name="hibernate.c3p0.max_size" value="15" /> <!-- 根据业务量设置合理最大值 -->
<property name="hibernate.c3p0.timeout" value="1800" /> <!-- 空闲30分钟后释放连接 -->
<property name="hibernate.c3p0.idle_test_period" value="600" /> <!-- 每10分钟检测一次空闲连接 -->
<property name="hibernate.c3p0.maxIdleTimeExcessConnections" value="300" /> <!-- 超量空闲连接5分钟后释放 -->

4. 排查代码中的连接泄漏

  • 用try-with-resources块管理EntityManager/Session,确保自动关闭:
    try (EntityManager em = entityManagerFactory.createEntityManager()) {
        // 数据库操作逻辑
    }
    
  • 利用hibernate.generate_statistics=true获取连接统计数据,通过SessionFactory.getStatistics()查看getConnectionOpenCount()等指标,定位未释放的连接来源。

5. 临时应急调整(可选)

若上述方案需要时间落地,可临时调高MySQL的max_connections参数(如设置为300),避免业务中断,但这只是临时措施,需尽快解决根本问题。


内容的提问来源于stack exchange,提问作者Aziz bouchtaoui

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 00:04:59