MySQL数据库连接池泄露导致MySQL Server超时关闭连接

前言

最近做项目,发现老项目出现xxx,这个错误其实很简单,出现在MySQL数据库Server端对长时间没有使用的client连接执行清楚处理,因为是druid数据库,且在github也出现这样的issue:The last packet successfully received from the server was 6,011 milliseconds ago. The last packet sent successfully to the server was 6,011 milliseconds ago.,所以怀疑是不是druid配置的问题,毕竟连接池会定时的检查连接,但是实际排查发现不是那么回事,是连接池泄露了,只不过并发不大,表现为{conn-10002} discard错误而已。

准备

按照笔者上次的文章mybatis plus相同Id与xml配置错误时,mybatis plus解决逻辑_mybatis plus xml文件查询id名字相同-CSDN博客

准备数据库,且通过开启root权限 

demo

demo简单写一下,实际项目肯定复杂很多

   <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId><version>2.7.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.22</version></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId><version>2.7.17</version></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.2</version></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency></dependencies>

写一个main controller dao

@SpringBootApplication
@MapperScan("org.example.druid.demo.dao")
public class DruidMain {public static void main(String[] args) {SpringApplication.run(DruidMain.class, args);}
}@RestController
public class DemoController {@Autowiredprivate UserDao userDao;@RequestMapping(value = "/demo", method = RequestMethod.GET)public String demo(){int num = userDao.updateUser();return "{\"update\" : " + num + "}";}
}@Mapper
public interface UserDao {@Update("update User set age = 30 where id = 1")int updateUser();
}

配置文件

spring.datasource.druid.url= jdbc:mysql://127.0.0.1:3306/demo?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
spring.datasource.druid.username= root
spring.datasource.druid.password= 123456i
spring.datasource.druid.driver-class-name= com.mysql.cj.jdbc.Driver
spring.datasource.druid.initialSize=2
spring.datasource.druid.minIdle=2
spring.datasource.druid.maxActive=2
spring.datasource.druid.maxWait=20000
spring.datasource.druid.timeBetweenEvictionRunsMillis=1000
spring.datasource.druid.minEvictableIdleTimeMillis=30000
spring.datasource.druid.validationQuery=SELECT 1
spring.datasource.druid.validationQueryTimeout=1
spring.datasource.druid.testOnBorrow=false
spring.datasource.druid.testOnReturn=false
spring.datasource.druid.testWhileIdle=true
spring.datasource.druid.keepAlive=true
spring.datasource.druid.socketTimeout=6000
spring.datasource.druid.poolPreparedStatements=true

访问 http://localhost:8080/demo

这一步实际上没什么问题,但是如果涉及编程式事务,那么可能出现代码逻辑漏洞

@Configuration
public class DemoConfiguration {@Beanpublic PlatformTransactionManager initPlatformTransactionManager(DruidDataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}@RestController
public class DemoController {@Autowiredprivate UserDao userDao;@Autowiredprivate PlatformTransactionManager transactionManager;@RequestMapping(value = "/demo", method = RequestMethod.GET)public String demo(){TransactionStatus transactionStatus = transactionManager.getTransaction(new DefaultTransactionDefinition());int num = 0;try {num = userDao.updateUser();transactionManager.commit(transactionStatus);} catch (TransactionException e) {transactionManager.rollback(transactionStatus);}return "{\"update\" : " + num + "}";}
}

这样写也没问题,但是,如果我们在事务拿到后,因为一些逻辑return呢

 设置MySQL的超时时间

通过临时设置或者永久设置,--来自bing AI搜索

比如我们临时设置1分钟试试,问题复现

表现为{conn-10002} discard

2025-02-25 21:52:26.692 DEBUG 2129 --- [nio-8080-exec-1] c.a.druid.pool.PreparedStatementPool     : {conn-10002, pstmt-20000} exit cache
2025-02-25 21:52:26.695 DEBUG 2129 --- [nio-8080-exec-1] com.alibaba.druid.util.JdbcUtils         : close connection error

排查过程

The last packet successfully received from the server was 6,006 milliseconds ago. The last packet sent successfully to the server was 6,006 milliseconds ago.

2025-02-25 21:52:26.690 ERROR 2129 --- [nio-8080-exec-1] druid.sql.Statement                      : {conn-10002, pstmt-20002} execute error. select * from Usercom.mysql.cj.jdbc.exceptions.CommunicationsException: The last packet successfully received from the server was 183,457 milliseconds ago. The last packet sent successfully to the server was 183,458 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.at com.mysql.cj.jdbc.exceptions.SQLError.createCommunicationsException(SQLError.java:175) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:64) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:916) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:354) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3462) [druid-1.2.22.jar:na]at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:434) [druid-1.2.22.jar:na]at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3460) [druid-1.2.22.jar:na]at com.alibaba.druid.wall.WallFilter.preparedStatement_execute(WallFilter.java:686) [druid-1.2.22.jar:na]at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3460) [druid-1.2.22.jar:na]at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:434) [druid-1.2.22.jar:na]at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3460) [druid-1.2.22.jar:na]at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.execute(PreparedStatementProxyImpl.java:158) [druid-1.2.22.jar:na]at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:483) [druid-1.2.22.jar:na]at org.apache.ibatis.executor.statement.PreparedStatementHandler.query(PreparedStatementHandler.java:65) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.statement.RoutingStatementHandler.query(RoutingStatementHandler.java:80) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.SimpleExecutor.doQuery(SimpleExecutor.java:65) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.BaseExecutor.queryFromDatabase(BaseExecutor.java:336) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.BaseExecutor.query(BaseExecutor.java:158) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:110) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.executor.CachingExecutor.query(CachingExecutor.java:90) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:154) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:147) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:142) [mybatis-3.5.14.jar:3.5.14]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_431]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_431]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_431]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_431]at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:425) [mybatis-spring-2.1.2.jar:2.1.2]at com.sun.proxy.$Proxy57.selectList(Unknown Source) [na:na]at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) [mybatis-spring-2.1.2.jar:2.1.2]at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:147) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:141) [mybatis-3.5.14.jar:3.5.14]at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86) [mybatis-3.5.14.jar:3.5.14]at com.sun.proxy.$Proxy61.selectUsers(Unknown Source) [na:na]at org.example.druid.demo.controller.DemoController.getUsers(DemoController.java:51) [classes/:na]at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_431]at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_431]at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_431]at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_431]at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205) [spring-web-5.3.30.jar:5.3.30]at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:150) [spring-web-5.3.30.jar:5.3.30]at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:117) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:895) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:808) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1072) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:965) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) [spring-webmvc-5.3.30.jar:5.3.30]at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898) [spring-webmvc-5.3.30.jar:5.3.30]at javax.servlet.http.HttpServlet.service(HttpServlet.java:529) [tomcat-embed-core-9.0.82.jar:4.0.FR]at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) [spring-webmvc-5.3.30.jar:5.3.30]at javax.servlet.http.HttpServlet.service(HttpServlet.java:623) [tomcat-embed-core-9.0.82.jar:4.0.FR]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:209) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:51) [tomcat-embed-websocket-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100) [spring-web-5.3.30.jar:5.3.30]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.30.jar:5.3.30]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93) [spring-web-5.3.30.jar:5.3.30]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.30.jar:5.3.30]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201) [spring-web-5.3.30.jar:5.3.30]at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:117) [spring-web-5.3.30.jar:5.3.30]at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:178) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:153) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:168) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:90) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:481) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:130) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:93) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:390) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:63) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:928) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1794) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:52) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.util.threads.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1191) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.util.threads.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:659) [tomcat-embed-core-9.0.82.jar:9.0.82]at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-9.0.82.jar:9.0.82]at java.lang.Thread.run(Thread.java:750) [na:1.8.0_431]
Caused by: com.mysql.cj.exceptions.CJCommunicationsException: The last packet successfully received from the server was 183,457 milliseconds ago. The last packet sent successfully to the server was 183,458 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method) ~[na:1.8.0_431]at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62) ~[na:1.8.0_431]at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45) ~[na:1.8.0_431]at java.lang.reflect.Constructor.newInstance(Constructor.java:423) ~[na:1.8.0_431]at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:62) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:105) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.exceptions.ExceptionFactory.createException(ExceptionFactory.java:150) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.exceptions.ExceptionFactory.createCommunicationsException(ExceptionFactory.java:166) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:582) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.NativeProtocol.checkErrorMessage(NativeProtocol.java:762) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.NativeProtocol.sendCommand(NativeProtocol.java:701) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.NativeProtocol.sendQueryPacket(NativeProtocol.java:1052) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.NativeSession.execSQL(NativeSession.java:657) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:893) ~[mysql-connector-j-8.0.33.jar:8.0.33]... 83 common frames omitted
Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.at com.mysql.cj.protocol.FullReadInputStream.readFully(FullReadInputStream.java:67) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.SimplePacketReader.readHeaderLocal(SimplePacketReader.java:81) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:63) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.SimplePacketReader.readHeader(SimplePacketReader.java:45) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:52) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.TimeTrackingPacketReader.readHeader(TimeTrackingPacketReader.java:41) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:54) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.MultiPacketReader.readHeader(MultiPacketReader.java:44) ~[mysql-connector-j-8.0.33.jar:8.0.33]at com.mysql.cj.protocol.a.NativeProtocol.readMessage(NativeProtocol.java:576) ~[mysql-connector-j-8.0.33.jar:8.0.33]... 88 common frames omitted

这个问题在github也有类似的情况,但是不一定是笔者遇到的问题:https://github.com/alibaba/druid/issues/5963

 对于连接泄露可以配置泄露连接强制回收,但是这个仅在排查问题使用

removeAbandoned: true
removeAbandonedTimeoutMillis: 30000 #(以毫秒数为单位)
logAbandoned: true

貌似有用,但是实际情况是占用数据库连接的线程并不一定是问题的代码逻辑,我这里仅仅写了一个controller,刚好对应上

所以排查还需要另外的思路,下面演示解决A的锅B来背的案例。

解决方法

开启连接池连接的状态日志,这里以druid为例

com.alibaba.druid.filter.logging.LogFilter

既然查看连接情况,那么这个最关键 

spring.datasource.druid.filters=stat,wall,slf4j
logging.level.com.alibaba.druid=TRACE
#最关键的日志
logging.level.druid.sql.Connection=TRACE

当然笔者使用的MySQL版本8.0,这里是客户端缓存,MySQL8.0已经删除了查询缓存,而且这里是更新操作,毕竟查询缓存命中效率比较低,还是吞吐量比较重要,还增加了查询重写插件

以另一个不是事务的请求为例,用于验证问题

update的连接调用

等待1分钟,并发多次请求查询连接后就会报错

错误日志分析

错误的id为10002,从日志往上追溯

这里就是查询业务背了开始更新业务的锅,毕竟查询没有事务。事务代码BUG导致连接没被连接池回收 ,但被查询业务使用了连接,而且有时候可能和mysql Server的一些超时断掉连接的特性结合,那么问题就复杂了。

找到问题就好处理有问题的代码了,毕竟解决问题很简单,找到问题很难。

总结

我们在写代码时,尽量还是使用框架封装的逻辑,比如连接池,比如Spring声明式事务,可以避免编程式事务在写代码时的逻辑漏洞,因为在没触发的时候很难出现,测试很多时候不充分。实际上一起写jdbc的时候还很少出现这个问题,因为那个时候会非常注意连接的回收,事务的提交逻辑,但是Spring自动管理后,这个就很少注意了,因为注解声明式事务太方便了,只有特殊时候才会自己管理事务。

另外这个问题具备隐蔽性,因为报错是MySQL驱动连接MySQL Server报超时未使用关闭连接,但是此处示例的根源却是编程式事务导致连接池泄露,单个问题实际上可以头痛医头,但是当一些mysqlServer的特性加持下,就变成了头痛医脚的感觉了,解决问题很容易,发现问题很难。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/23844.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DirectX12(D3D12)基础教程三 线性代数与3D世界空间

线性代数是数学的一个分支&#xff0c;它的研究对象是向量&#xff0c;向量空间&#xff08;或称线性空间&#xff09;&#xff0c;线性变换和有限维的线性方程组。 向量和矩阵是学习3D入门最基本的理论基础。本章重点讲向量和矩阵. 向量概念 向量最基本的定义就是一个方向和…

LeetCode 230.二叉搜索树中第K小的元素

题目&#xff1a;给定一个二叉搜索树的根节点 root &#xff0c;和一个整数 k &#xff0c;请你设计一个算法查找其中第 k 小的元素&#xff08;从 1 开始计数&#xff09;。 思路&#xff1a; 代码&#xff1a; /*** Definition for a binary tree node.* public class Tre…

Android 老项目 jcenter 库失效

最近重新维护了一些老项目发现大部分jcenter库失效了&#xff0c; Could not resolve com.xx:2.1.3. 如果你也遇到了&#xff0c;不妨试试 替换为 aliyun的jcenter服务&#xff0c;就不用一个个找代替库了。 project 下的 build.gradle 文件添加&#xff1a; maven { url htt…

Python数据结构:哈希表-高效存储与查找的秘密武器!

大家周一好&#xff01;今天我们来聊聊Python中一个非常重要的数据结构——哈希表。无论是算法面试还是实际开发&#xff0c;哈希表都扮演着至关重要的角色。掌握它&#xff0c;你就能轻松解决许多复杂的编程问题&#xff01; 在编程中&#xff0c;如何实现快速的存储与查找操…

【复习】Redis

数据结构 Redis常见的数据结构 String&#xff1a;缓存对象Hash&#xff1a;缓存对象、购物车List&#xff1a;消息队列Set&#xff1a;点赞、共同关注ZSet&#xff1a;排序 Zset底层&#xff1f; Zset底层的数据结构是由压缩链表或跳表实现的 如果有序集合的元素 < 12…

【电机控制器】ESP32-C3语言模型——DeepSeek

【电机控制器】ESP32-C3语言模型——DeepSeek 文章目录 [TOC](文章目录) 前言一、简介二、代码三、实验结果四、参考资料总结 前言 使用工具&#xff1a; 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、简介 二、代码 #include <Arduino.h&g…

STM32-智能小车项目

项目框图 ST-link接线 实物图&#xff1a; 正面&#xff1a; 反面&#xff1a; 相关内容 使用L9110S电机模块 电机驱动模块L9110S详解 | 良许嵌入式 一、让小车动起来 新建文件夹智能小车项目 在里面复制19-串口打印功能 重命名为01-让小车动起来 新建文件夹motor&…

Redis基础学习

目录 Redis命令 通用命令 String Key的顶层格式 Hash List ​编辑​编辑Set SortedSet 在IDEA使用Jedis操作Redis 常规使用 Jedis的连接池 SpringDataRedis 手动序列化和反序列化 操作Hash Redis命令 通用命令 想知道某个命令怎么用 1.可以在官网学习用法 h…

ASP.NET Core Clean Architecture

文章目录 项目地址一、项目主体1. CQRS1.1 Repository数据库接口1.2 GetEventDetail 完整的Query流程1.3 创建CreateEventCommand并使用validation 2. EFcore层2.1 BaseRepository2.2 CategoryRepository2.3 OrderRepository 3. Email/Excel导出3.1 Email1. IEmail接口层2. Ema…

MySQL数据库——表的约束

1.空属性&#xff08;null/not null&#xff09; 两个值&#xff1a;null&#xff08;默认的&#xff09;和not null&#xff08;不为空&#xff09; 数据库默认字段基本都是字段为空&#xff0c;但是实际开发时&#xff0c;尽可能保证字段不为空&#xff0c;因为数据为空没办法…

DeepSeek-R1:通过强化学习激发大语言模型的推理能力

注&#xff1a;此文章内容均节选自充电了么创始人&#xff0c;CEO兼CTO陈敬雷老师的新书《自然语言处理原理与实战》&#xff08;人工智能科学与技术丛书&#xff09;【陈敬雷编著】【清华大学出版社】 文章目录 DeepSeek大模型技术系列三DeepSeek大模型技术系列三》DeepSeek-…

蓝桥杯备考:递归初阶之汉诺塔问题

我们只要想一个主问题&#xff0c;我们是先把a上面n-1个盘子放在c里&#xff0c;然后再把第n个盘子放在b上&#xff0c;再利用a把c上n-1个盘子都放在b上就行了 #include <iostream> using namespace std;void dfs(int n,char x,char y,char z) {if(n0) return;dfs(n-1,x…

聊一聊vue如何实现角色权限的控制的

大家好&#xff0c;我是G探险者。 关于角色与权限控制&#xff0c;通常是分为两大类&#xff1a;一种是菜单权限&#xff1b;一种是操作权限。 菜单权限是指&#xff0c;每个角色对应着可以看到哪些菜单&#xff0c;至于每个菜单里面的每个按钮&#xff0c;比如增删改查等等这类…

如何将公钥正确添加到服务器的 authorized_keys 文件中以实现免密码 SSH 登录

1. 下载密钥文件 2. RSA 解析 将 id_ed25519 类型的私钥转换为 RSA 类型&#xff0c;要将 ED25519 私钥转换为 RSA 私钥&#xff0c;需要重新生成一个新的 RSA 密钥对。 步骤&#xff1a; 生成新的 RSA 密钥对 使用 ssh-keygen 来生成一个新的 RSA 密钥对。比如&#xff0c;执…

RK Android11 WiFi模组 AIC8800 驱动移植流程

RK Android WiFi模组 AIC8800 驱动移植流程 作者&#xff1a;Witheart更新时间&#xff1a;20250220 概要&#xff1a;本文介绍了基于 AIC8800D40 芯片的 WiFi6 模组 BL-M8800DS2-40 在 RK3568 平台上的驱动移植流程。主要涉及环境搭建、驱动代码分析、设备树修改、驱动编译配…

力扣3102.最小化曼哈顿距离

力扣3102.最小化曼哈顿距离 题目 题目解析及思路 题目要求返回移除一个点后的最小的最大曼哈顿距离 最大最小值的题一般直接想到二分 本题有一个简单办法就是利用切比雪夫距离 当正方形转45&#xff0c;即边上点**( x , y ) -> (x y , y - x)时&#xff0c;两点间max(…

BUUCTF--[极客大挑战 2019]RCE ME

目录 URL编码取反绕过 异或绕过 异或的代码 flag 借助蚁剑中的插件进行绕过 利用动态链接库 编写恶意c语言代码 进行编译 然后再写一个php文件 将这两个文件上传到/var/tmp下 运行payload 直接看代码 <?php error_reporting(0); if(isset($_GET[code])){$code$_G…

Linux----线程

一、基础概念对比 特性进程 (Process)线程 (Thread)资源分配资源分配的基本单位&#xff08;独立地址空间&#xff09;共享进程资源调度单位操作系统调度单位CPU调度的最小单位创建开销高&#xff08;需复制父进程资源&#xff09;低&#xff08;共享进程资源&#xff09;通信…

Missing required prop: “maxlength“

背景&#xff1a; 封装一个使用功能相同使用频率较高的input公共组件作为子组件&#xff0c;大多数长度要求为200&#xff0c;且实时显示统计子数&#xff0c;部分input有输入提示。 代码实现如下&#xff1a; <template><el-input v-model"inputValue" t…

DeepSeek引领目标检测新趋势:如何通过知识蒸馏优化模型性能

目录 一、知识蒸馏是什么&#xff1f; 二、知识蒸馏在目标检测中的重要性 提升实时性 跨任务迁移学习 三、如何使用知识蒸馏优化目标检测&#xff1f; 训练教师模型 生成软标签 训练学生模型 调节温度参数 多教师蒸馏&#xff08;可选&#xff09; 四、案例分享 定…