返回
数据库连接池提前初始化引发的异常及解决办法
后端
2023-10-24 18:52:54
数据库连接池提前初始化引发的异常
背景
我们线上一个项目在发版本时,经常会有部分实例无法正常启动的情况,特别是在没有进行灰度发布的场景下,基本上很难正常的启动成功,异常信息如下:
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'dataSource' defined in class path resource [org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration$HikariConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariDataSource]: Factory method 'dataSource' threw exception; nested exception is java.lang.IllegalStateException: driverClassName specified twice [com.mysql.jdbc.Driver, com.mysql.cj.jdbc.Driver]
问题分析
看日志可以很容易看出来,启动异常的原因是hikaricp
连接池初始化异常,经过排查,是因为同时引入了两个mysql驱动引起的,于是删除一个驱动,问题解决
。
解决办法
将代码中的mysql-connector-java-5.1.46.jar
文件删除,再重启项目,问题解决。
以下是本次异常的一些思考和总结:
-
hikari
数据库连接池中,如果指定了连接池类名,那么在构建数据源时,就不会使用SpringBoot默认的配置,例如:spring.datasource.driver-class-name
。 -
hikari
在初始化连接池时,会先判断是否已经有数据源的连接池了,如果已经有的话就不会在创建,所以我们在自定义数据源时,千万不要忘记销毁连接池。 -
hikari
连接池默认在启动时不会进行预热,如果连接池中没有连接,那么第一次使用时,会比较慢,所以我们可以通过以下方式开启连接池的预热。
spring:
datasource:
hikari:
connection-test-query: isValid
minimum-idle: 5
maximum-pool-size: 10
idle-timeout: 30000
max-lifetime: 1800000
- 如果使用了连接池的话,那么在做数据库操作时,一定要注意不要忘记关闭连接,否则会导致连接泄露。
总结
数据库连接池是提高数据库连接性能的重要工具,但是使用时需要注意一些细节,否则容易出现异常。
在使用hikari
连接池时,如果指定了连接池类名,那么在构建数据源时,就不会使用SpringBoot默认的配置,所以我们在自定义数据源时,千万不要忘记销毁连接池。
hikari
连接池默认在启动时不会进行预热,如果连接池中没有连接,那么第一次使用时,会比较慢,所以我们可以通过设置connection-test-query
来开启连接池的预热。
如果使用了连接池的话,那么在做数据库操作时,一定要注意不要忘记关闭连接,否则会导致连接泄露。