当前位置:网站首页>Could not open JDBC connection for transaction
Could not open JDBC connection for transaction
2022-06-29 09:47:00 【milugloomy】
background
The company recently reported this error in the online project ,Could not open JDBC Connection for transaction, Unable to get the data source connection pool .
analysis
Read the source code , Let's see if the data source connection can be automatically released in all cases .
MyBatis Release the connection
MyBatis Run when running alone SQL Statement will not automatically release the data source connection , But and Spring After consolidation, the data source connection will be automatically released .Spring Changed the MyBatis Of SqlSession, Change to Spring In the integration package SqlSessionTemplate, The key codes are as follows :
public class SqlSessionTemplate implements SqlSession, DisposableBean {
//...
// Omit some code
private class SqlSessionInterceptor implements InvocationHandler {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
SqlSession sqlSession = getSqlSession(
SqlSessionTemplate.this.sqlSessionFactory,
SqlSessionTemplate.this.executorType,
SqlSessionTemplate.this.exceptionTranslator);
try {
Object result = method.invoke(sqlSession, args);
if (!isSqlSessionTransactional(sqlSession, SqlSessionTemplate.this.sqlSessionFactory)) {
sqlSession.commit(true);
}
return result;
} catch (Throwable t) {
Throwable unwrapped = unwrapThrowable(t);
if (SqlSessionTemplate.this.exceptionTranslator != null && unwrapped instanceof PersistenceException) {
// release the connection to avoid a deadlock if the translator is no loaded. See issue #22
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
sqlSession = null;
Throwable translated = SqlSessionTemplate.this.exceptionTranslator.translateExceptionIfPossible((PersistenceException) unwrapped);
if (translated != null) {
unwrapped = translated;
}
}
throw unwrapped;
} finally {
if (sqlSession != null) {
closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory);
}
}
}
}
}
At the end of the finally in , Will close session, Release data source connection .
Business @Transactional Release the connection
Add comments to methods @Transactional Mark the method as a transaction , The connection will also be automatically released , The key codes are as follows :
public class DataSourceTransactionManager extends AbstractPlatformTransactionManager
implements ResourceTransactionManager, InitializingBean {
//...
// Omit some code
@Override
protected void doCleanupAfterCompletion(Object transaction) {
DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
if (txObject.isNewConnectionHolder()) {
TransactionSynchronizationManager.unbindResource(this.dataSource);
}
Connection con = txObject.getConnectionHolder().getConnection();
try {
if (txObject.isMustRestoreAutoCommit()) {
con.setAutoCommit(true);
}
DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel());
}
catch (Throwable ex) {
logger.debug("Could not reset JDBC Connection after transaction", ex);
}
if (txObject.isNewConnectionHolder()) {
if (logger.isDebugEnabled()) {
logger.debug("Releasing JDBC Connection [" + con + "] after transaction");
}
DataSourceUtils.releaseConnection(con, this.dataSource);
}
txObject.getConnectionHolder().clear();
}
Among them ,DataSourceUtils.releaseConnection(con, this.dataSource) Method closes the data source connection .
To find problems
The company project uses Druid data source , The maximum number of connections is set to 50, Follow the above analysis , Under normal circumstances, it is impossible to use up , There must be some code that doesn't release the connection .
I've been looking for it for a long time , Finally locate the following code :
@Autowired
private SqlSessionFactory sqlSessionFactory;
public void batchInsert(List<TaskCenter> list) {
if(list == null || list.size() == 0){
return;
}
try {
SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TaskCenterMapper mapper = sqlSession.getMapper(TaskCenterMapper.class);
for(TaskCenter taskCenter : list){
mapper.insertSelective(taskCenter);
}
sqlSession.flushStatements();
sqlSession.commit();
log.info(" Batch insert succeeded : " + list.size()+" Data ");
}catch (Exception ex){
log.error(" Batch insert failed : ", ex);
}
}
This code means to use MyBatis Batch insert function of batch insert data , We analyzed above , Use MyBatis Of SqlSession The data source connection will not be closed automatically , Need to use Spring Packed SqlSessionTemplate Will automatically close the data source connection . So every time you execute this batchInsert Method , Will occupy a data source connection without releasing , Eventually, the data source connection pool is full , Unable to open new connection .
solve the problem
Based on the above analysis , There are two solutions to this problem
1、 Add this method to the transaction , Add a comment to the method @Transactional, The code is as follows :
@Transactional
public void batchInsert(List<TaskCenter> list) {
if(list == null || list.size() == 0){
return;
}
// Omitted below
// ...
2、 Use up sqlSession Manual closing after sqlSession, The code is as follows :
public void batchInsert(List<TaskCenter> list) {
if(list == null || list.size() == 0){
return;
}
SqlSession sqlSession = null;
try {
sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH);
TaskCenterMapper mapper = sqlSession.getMapper(TaskCenterMapper.class);
for(TaskCenter taskCenter : list){
mapper.insertSelective(taskCenter);
}
sqlSession.flushStatements();
sqlSession.commit();
log.info(" Batch insert succeeded : " + list.size()+" Data ");
}catch (Exception ex){
log.error(" Batch insert failed : ", ex);
}finally {
if (sqlSession != null) {
SqlSessionUtils.closeSqlSession(sqlSession, sqlSessionFactory);
}
}
}
Conclusion
According to a production problem, this article analyzes the source code to understand MyBatis The framework and Spring Transaction management automatically turns off the data source connection pool , Understand the principle to solve the problem .
边栏推荐
- 数据处理时代,数据质量建设才是企业的生存之道
- In the era of data processing, data quality construction is the way for enterprises to survive
- Student增删gaih
- 证券账号开户安全吗?是靠谱的吗?
- 滑块验证代码
- 数据治理:元数据管理(第二篇)
- Segmentation of Head and Neck Tumours Using Modified U-net
- Have you done the network security "physical examination" this year?
- UE4 蓝图修改Array 中Get a copy 为 reference
- Mysql配置主从数据库
猜你喜欢

A 2.5D Cancer Segmentation for MRI Images Based on U-Net

1424. 对角线遍历 II

UE4 material UV texture does not stretch with model scale

你知道BFD是什么吗?一文详解BFD协议原理及使用场景

Wechat applet user refuses to authorize geographic location information and calls up the authorization window again

A 3D Dual Path U-Net of Cancer Segmentation Based on MRI

UE4 animation redirection

In the future of Business Intelligence BI, how do you view the ai+bi model?

UE4 remove the mask transparent white edge in the material

MySQL configuring master-slave databases
随机推荐
UE4 在4.20-23版本安裝Datasmith插件
easyexecl导出100万行execl报字体错误的解决办法
LSM6DSL之SPI驱动
UE4 在viewport视口中显示3D可编辑点
After aikuai is installed or reset, the PC or mobile terminal cannot obtain IP
Mongodb persistence
MySQL configuring master-slave databases
Data warehouse: layered architecture of Finance / banking
UE4 材质UV纹理不随模型缩放拉伸
Pytorch summary learning series - operation
Pytorch summary learning series - broadcast mechanism
Automatic Multi-Organ SegmVentation on Abdominal CT With Dense V-Networks
《网络是怎么样连接的》读书笔记 - WEB服务端请求和响应(五)
Simplicity Studio无法识别新买的JLink v9解决方法
数据源连接池未关闭的问题 Could not open JDBC Connection for transaction
Introduction to Chang'an chain data storage and construction of MySQL storage environment
五心公益红红娘团队
你必须知道的23个最有用的Elasticseaerch检索技巧
UE4 blueprint modify get a copy in array to reference
基于PyQt5和Qt Designer的简易加法计算器的制作