现象描述:
数据库操作采用的是spring-data-jpa,测试操作数据库的单元测试整个文件执行是成功的,但是发布到流水线自动化编译是报错:
o.h.engine.jdbc.spi.SqlExceptionHelper : SQL Error: 1040, SQLState: 08004,
o.h.engine.jdbc.spi.SqlExceptionHelper : Too many connections
解决过程:
使用show variables like “max_connections”;可以查看数据库的最大连接数,显示为240,
使用show processlist可以查看数据库当前的连接情况,显示为135
单元测试数量比较多,有34个,很多都用到了@SpringBootTest注解,在本地使用mvn test执行单元测试,通过show processlist实时查看数据库连接数发现在执行单元测试的过程中,数据库的连接数由原来的135快速增加到200,最后达到238,接近数据库设置的最大连接数,最后执行数据库操作的单元测试报错,关键的错误信息为Too many connection.
单元测试执行完之后,数据库连接数又恢复了原来的135,说明单元测试执行完之后执行中建立的连接数都被释放了。
猜想与单元测试比较多有关,在部分单元测试上增加@Ignore注解,取消执行,再次执行mvn test,实时查看数据库连接发现连接数增加到200之后没有再增加,最后的单元测试执行都成功了
原因分析:
SpringBoot数据库连接池默认使用的是Tomcat连接池,通过查资料发现tomcat连接池启动时创建的初始连接数量默认为10,每次执行添加了@SpringBootTest注解的单元测试时,springboot都会去创建连接池,如果创建了15个连接池,默认就会初始化150个连接数,加上数据库原来的连接数,就会超过Mysql数据库默认的最大连接数,而程序正常启动时只会创建一个连接池,所以正常使用时没有问题的,但是单元测试中如果很多地方用到了@SpringBootTest就有可能会有问题,因为每次SpringBoot启动时都会去初始化连接池,由于单元测试执行时间一般都很多来不及释放连接,就会导致执行所有单元测试时总的连接数超过了数据库设置的最大连接数。
解决方法:
在test/resources目录下为单元测试文件添加application.properties,并在其中设置数据库连接池初始化连接数为1,最大活跃是2
spring.datasource.max-active=2
spring.datasource.initialSize=1
该配置文件只会影响单元测试,不会影响正常的程序执行。
参考资料:
Springboot默认数据库连接池及常用属性:https://blog.csdn.net/m0_37754003/article/details/83582263