平常开发或测试中,没有用到数据库连接池可能也测试不出来,但是一旦到线上出现一定数量的并发,就会损失惨重。
在没有数据库连接池的情况,有30个并发,出现
Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: UPDATE t_record SET `status` = '1' WHERE `code` = ? AND `status` IN ('0','2')
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; SQL []; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
所以可以看出数据库连接池的重要。
以Druid为例,看一下数据库连接池的配置:
maven引入:
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.10</version>
</dependency>
spring boot 配置上
spring:
datasource:
url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf8
username: root
password: 1234
driver-class-name: com.mysql.jdbc.Driver
#initialSize: 32
#minIdle: 5
#maxActive: 128
type: com.alibaba.druid.pool.DruidDataSource
platform: mysql
dbcp2:
min-idle: 5
max-idle: 128
initial-size: 32
@Configuration
@MapperScan(basePackages = "com.ranying", sqlSessionFactoryRef = "sqlSessionFactory")
public class DataSourceConfig {
略...
@Value("${spring.datasource.dbcp2.max-idle}")
private Integer maxActive;
@Value("${spring.datasource.dbcp2.min-idle}")
private Integer minIdle;
@Value("${spring.datasource.dbcp2.initial-size}")
private Integer initialSize;
@Bean(name = "dataSource")
@Primary
public DataSource dataSource() throws SQLException {
com.alibaba.druid.pool.DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(dbDriver);
dataSource.setUrl(dbUrl);
dataSource.setUsername(dbUser);
dataSource.setPassword(dbPassword);
// 最大连接池数量
dataSource.setMaxActive(maxActive);
dataSource.setMinIdle(minIdle);
dataSource.setInitialSize(initialSize);
/* dataSource.setMaxOpenPreparedStatements(32);
dataSource.setValidationQuery("select 1 from tcs_record limit 1 ");
dataSource.setTestWhileIdle(true);*/
// 初始化,如果不加,默认会在第一次调用数据库连接数初始化
dataSource.init();
return dataSource;
}
验证环节:
1、执行sql : show full processlist 查看现在已经有的链接
2、启动项目
注意:如果没加 dataSource.init(); 那么启动项目不进行数据库操作的情况下,不会增加连接
3、再次执行 show full processlist; 查看连接是不是 增加到了 InitialSize 个链接(排除别人也在连的情况)
4、写个测试循环耗尽数据库链接
注意在Controller层,不要在同一个事务
for (int i = 0; i < 10000; i++) {
testMapper.getById(100);
}
观察数的变化