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
相关产品推荐
相关产品推荐

