事务和连接池配合使用存在的问题

前言

今天讨论一个问题,如果全部方法都加上事务,会不会有问题?

前两天看到一个老项目,xml方式的配置,拦截了所有的方法,增加了事务,不能说它的做法有问题,也不能说不对。

例子

下面hikari配置了一个连接池:

最大个数20个,获取链接等待5秒

spring:
  application:
    name: data-import
  datasource:
    url: jdbc:mysql://localhost:3306/data-import?useSSl=true&zeroDateTimeBehavior=convertToNull&characterEncoding=utf-8&serverTimezone=GMT%2B8
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
    hikari:
      minimum-idle: 5
      idle-timeout: 1000
      maximum-pool-size: 20
      auto-commit: true
      pool-name: datimportpool
      max-lifetime: 1800000
      connection-timeout: 5000
      connection-test-query: SELECT 1

再增加一个接口

注意:这里我增加了线程睡眠时间,模拟业务处理慢的情况

@RestController
@RequestMapping("/test")
public class TestController {

    @Transactional
    @GetMapping("/get")
    public Object get() throws InterruptedException {
        TimeUnit.SECONDS.sleep(2);
        return "xx";
    }
}

结果

我们用jmeter压测看看

100的并发量,吞吐量只有14,并且还有异常的

image-20240201212439894

image-20240201213234030

image-20240201213213760

异常就是获取connection超时:

image-20240201212538110

我们查看下mysql它默认的链接数

# 查看mysql的最大链接数
show variables like '%max_connections%';

# 查看每个用户的最大链接数
show variables like 'max_user_connections';

image-20240201212733633

实际情况需要根据环境来进行配置,这里作为测试,修改应用的最大链接数到50

image-20240201213351516

image-20240201213406454

image-20240201213425101

结论:

  1. 业务处理慢的接口,会占用连接池资源,导致后续接口的等待,严重的导致超时异常;
  2. 加入了事务的方法,不论是否使用了jdbc,都会受限于数据库连接池的限制,也就是会产生性能瓶颈,虽然说连接池是为了提高系统性能,避免资源浪费,但是在业务处理慢的时候是相反的;

源码

上面我们是通过表象去看待问题,下面我们通过源码去看它的过程。

关于事务详细的源码分析看:spring源码篇(八)事务的原理-CSDN博客

spring事务有动态代理实现,实现逻辑在TransactionAspectSupport

org.springframework.transaction.interceptor.TransactionAspectSupport

image-20240202203151187

最后他会走到这个位置:

org.springframework.jdbc.datasource.DataSourceTransactionManager#doBegin

在这里他会通过dataSource获取一个connection

image-20240202203838274

看一下这个绑定的方法

image-20240202203912931

image-20240202203926150

这里以datasource为键,connectionHandle为value放到了resources中,而resources这个是线程变量ThreadLocal,只对当前线程有效,到这里,大概的一个流程我们梳理一下

image-20240202205703870

所以说当业务逻辑执行慢的时候,就会占用一个connection资源不释放,当连接池的Connection达到上限时就会使得后面的请求等待,当等待时间达到设置的超时时间就会抛出timeout的异常。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值