事务未提交和连接未关闭
背景
最近一个项目出现了应用服务器无法登录的现象.
出现现象后,给出了jstack和应用的log等信息.
jstack 里面所有的 http的nio 线程都在parked状态.
然后log里面出现了大量的获取不到链接的提示.
所以第一反应是因为事务未提交导致的连接池泄露.
但是后续与同事一起看问题时发现, 并没有未提交的事务.
所以感觉自己可能对 事务未提交和连接未关闭的场景产生了混淆.
所以想着能够总结一下两种场景, 希望能够学习和提高.
现象
所有的工作线程都进入 parked的状态:
"http-nio-5200-exec-179" #59186 daemon prio=5 os_prio=0 tid=0x00007f4d941ca800
nid=0x28e3da waiting on condition [0x00007f4b976f9000]
java.lang.Thread.State: TIMED_WAITING (parking)
服务器没有压力 CPU/内存都很低
应用服务器的日志显示:
Failed to obtain JDBC Connection; nested exception is java.sql.SQLTransientConnectionException:
tenancy-connection01 - Connection is not available, request timed out after 30000ms
数据库显示有大量的正在执行的SQL,并且链接未关闭,能够查询出来.
区别和理解-事务未提交
事务未提交和连接未关闭其实是两个维度的问题.
事务未提交可能链接已经被关闭了.
这种问题很有可能是 finally 里面有connection的 dispose或者是close的命令
但是存在有 未被捕获的异常导致 transaction 没有commit/rollback 的情况.
导致应用线程(大部分为http-nio)返回给连接池管理的数据库链接(hikari后者是durid)里面还存在未提交的事务.
因为应用已经将connection返回给了 pool , 所以pool认为此connection 可以进行服用.
然后再给其他申请connection的 thread 时, thread 要commit 事务时就会报错, 因为前面存在未rollback的事务.
导致自己的产品出现异常. 所以这个时候, 就会出现施暴者没有反馈, 但是受害者再惨叫的情况.
此时需要关注的是 链接关闭时, 如果打开链接的线程堆栈忘记了事务的 commit/rollback 需要记录下来.
这类错误肯定会导致应用上有人报错, 但是报错的不是施暴者, 提前发现很重要. 可以避免问题爆发.
区别和理解-链接未关闭
链接未关闭的情况时 事务可能未提交, 也可能已经提交了.
不管事务有没有提交, 那么就需要足够多的异常操作,将连接池占满,导致应用不可用.
此时需要关注hikari等的连接数指标.
如果连接数指标单调递增没有下降的趋势, 并且没有应用反馈存在事务条失败的问题时:
很有可能出现了链接未关闭的问题
需要注意一般情况下连接未关闭时一个比较缓慢的过程. 并且如果业务操作非常低频率
可能很久也发现不了问题.
但是当存在一种比较2B的代码时可能瞬间将应用服务器的连接池打满
那就是 for循环或者是递归调用 sql执行, 同事没有关闭数据库链接.
比如连接池设置为100 , 然后一个大于100 的循环内打开链接进行insert 或者是update
并且链接不关闭. 那么很快应用机会不可用,出现宕机的情况.
防范方法
1. 可以通过代码的规范化检查来避免此类问题.
2. 通过代码规范, 避免手工建立连接,并且不进行释放来处理.
3. 测试时需要考虑足够多的场景, 尤其是数据量, 避免小数据量的情况无法发现问题.
4. 必须增加监控指标, 避免测试环境经常重启导致问题外泄.
5. 举一反三,增加研发培训, 对新员工增加严重问题代码的培训和宣贯.
其他理解
java运行其实是通过jvm虚拟机来进行处理的.
jvm其实可以理解为一个小型的linux系统.
既然是虚拟机, 是操作系统, 那么资源就是系统最重要的资产.
关闭资源就是系统最重要的工作.
CPU/内存/线程/文件句柄/链接(http,db) 都是系统中的资源.
任何一种资源受到过量的使用都会像癌症一样蔓延到其他的资源.
最终导致系统不可用.
解决问题的核心其实在于找到那种资源收到了过量的使用.
并且找到过量使用的始作俑者.
经历过问题锤炼, 并且有足够的记忆力和敏感度就非常重要了.
遇到问题需要做有根据的假设,并且进行求证.
但是不能无条件无理由的假设, 调查时的错误假设会导致调查失败.
调查失败会导致产品不可用, 影响很坏.
标签:事务,提交,连接,线程,关闭,链接,连接池
From: https://www.cnblogs.com/jinanxiaolaohu/p/17986271