美文网首页
REQUIRES_NEW导致数据库连接死锁

REQUIRES_NEW导致数据库连接死锁

作者: 十毛tenmao | 来源:发表于2019-07-17 23:38 被阅读0次

在项目中,我们使用Spring事务传播类型REQUIRES_NEW实现了子事务的独立性,但是在高并发的情况下出现了数据库连接获取不到的问题

问题症状

当出现较大并发访问系统时,比如30并发,则会出现以下错误

CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool1 - Connection is not available, request timed out after 30000ms.

获取数据库连接的时间居然超过了30秒,正常情况下一个请求的处理时间是200ms,所以觉得特别奇怪。 按说即使数据库连接数小于请求并发数,因为数据库连接是共享的,请求也可以很快地获取到数据库连接并完成请求。但是实际却超过了30秒。

查看连接池情况

  • 从连接池信息可以看出,当请求并发量很大时,连接数确实不够。而且最大连接数已经是100(默认是10)
HikariPool1 - Before cleanup stats (total=22, active=0, idle=22, waiting=0)
HikariPool1 - Before cleanup stats (total=49, active=49, idle=0, waiting=87)
oikariPool1 - Before cleanup stats (total=100, active=100, idle=0, waiting=70)
HikariPool1 - Before cleanup stats (total=100, active=0, idle=100, waiting=0)
HikariPool1 - Before cleanup stats (total=100, active=0, idle=100, waiting=0)

查看日志,觉得更加奇怪了,请求并发数是30,连接数已经是100了,但是还是不够。 所以怀疑连接泄漏了。但是使用的Spring Boot来管理连接池,并不是手动使用连接池,应该不可能是泄漏了。

查看请求日志

  • 查看一个请求中数据库连接相关的日志
Acquired Connection [HikariProxyConnection@880338874 wrapping com.mysql.cj.jdbc.ConnectionImpl@332c8129] for JDBC transaction
Switching JDBC Connection [HikariProxyConnection@880338874 wrapping com.mysql.cj.jdbc.ConnectionImpl@332c8129] to manual commit
...
Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@726cda03]
Acquired Connection [HikariProxyConnection@1154774545 wrapping com.mysql.cj.jdbc.ConnectionImpl@4664e639] for JDBC transaction
Switching JDBC Connection [HikariProxyConnection@1154774545 wrapping com.mysql.cj.jdbc.ConnectionImpl@4664e639] to manual commit

...
Transaction synchronization suspending SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@571ff6bc]
Acquired Connection [HikariProxyConnection@356317124 wrapping com.mysql.cj.jdbc.ConnectionImpl@1e0e3cb5] for JDBC transaction
Switching JDBC Connection [HikariProxyConnection@356317124 wrapping com.mysql.cj.jdbc.ConnectionImpl@1e0e3cb5] to manual commit

从这个日志中Transaction synchronization suspending SqlSession可以看到,因为使用Spring事务的REQUIRES_NEW传播类型,导致一个请求会同时占用多个连接,没有释放。这样就可能导致获取连接的死锁

解决办法

  • 设置连接超时时间,当获取连接的时间超过阈值时,就会退出事务,释放事务占用的连接。这样就可以破坏死锁条件spring.datasource.hikari.connection-timeout: 3000

参考

相关文章

  • REQUIRES_NEW导致数据库连接死锁

    在项目中,我们使用Spring事务传播类型REQUIRES_NEW实现了子事务的独立性,但是在高并发的情况下出现了...

  • MySQL死锁、资源竞争死锁

    什么是MySQL死锁: 什么是资源竞争死锁: 比如连接池 ShardingSphere文档中写到关于 数据库连接的...

  • 记录一次Mysql死锁排查过程

    背景 以前接触到的数据库死锁,都是批量更新时加锁顺序不一致而导致的死锁,但是上周却遇到了一个很难理解的死锁。借着这...

  • 记录一次Mysql死锁排查过程

    背景 以前接触到的数据库死锁,都是批量更新时加锁顺序不一致而导致的死锁,但是上周却遇到了一个很难理解的死锁。借着这...

  • spring事务隔离导致数据库连接耗尽而死锁

    记一次压测排查死锁 概述 应用背景 应用是公司内部的基础设施平台,会接收到多个内部平台的数据上报,考虑到后期可能接...

  • Java多线程之死锁(Deadlock)及死锁避免(Deadlo

    线程死锁(Thread Deadlock) 数据库死锁(Database Deadlocks) 死锁避免 (Dea...

  • mysql 问题排查常用方法

    输出数据当前状态 可用于排查死锁问题,锁定行数等问题 查询数据库连接信息 查询事务信息 查询数据库锁等待信息 手动...

  • channel实现原理

    参考连接 面是一些死锁的例子 1、 上面情况,向非缓冲通道写数据会发生阻塞,导致死锁。解决办法创建缓冲区 ch :...

  • oracle数据库死锁的检查方法

    转自:数据库死锁的检查方法 数据库死锁的检查方法 一、 数据库死锁的现象程序在执行的过程中,点击确...

  • 数据库连接池——Druid

    JDBC访问数据库的步骤 建立数据库连接 执行SQL语句 关闭数据库连接以上环节,在数据库频繁访问的时候,会导致数...

网友评论

      本文标题:REQUIRES_NEW导致数据库连接死锁

      本文链接:https://www.haomeiwen.com/subject/mhlhlctx.html