自学内容网 自学内容网

浅谈spring事务解决数据库连接超时问题

线上问题

服务正常,cpu使用率正常,内存使用率正常,接口长时间无返回,最后日志打印数据库连接超时。。。

关于mysql的事务隔离级别

mysql的事务隔离级别是可重复读,这个事务级别的设计为了保证事务开始到结束,查看的内容是保持一致的,在开发者的眼中就是同一个事务中没有修改情况下,数据的的任意位置select得到的结果是相同的,如果修改了,修改后的情况与select得到的情况保持一致,这就完全不用考虑被别的因素所干扰了。

关于spring的事务

spring的事务实现根本上还是需要依靠数据库的事务来实现,简单一点说就是数据库事务的startTransaction、commitTransaction 和 abortTransaction交给spring来管理。

spring的事务带来的问题

首先需要明确几个共识:
第一,数据库的连接数是有限的;
第二,项目通常采用连接池来管理数据库连接;
第三,当连接池的连接都被占用,就会出现无连接可用的情况。

基于上面的共识,就很容出现一个情况:
当并发请求执行时间较长并长时间占有数据库的连接,将会导致服务短时间无法提供有关使用到数据库的服务。在实际生产环境中,遇到某一时间点存在并发请求导致服务假死停服的情况,服务重启后解决问题,但是实际上等于中断了正在执行任务的线程,释放了数据库连接,重启后没有并发攻击,所以看起来解决了问题而已。

优化事务范围

spring项目通常是使用 @Transactional(rollbackFor = Exception.class) 来定义事务范围,可能有些小伙伴直接将这个注解放在service类的上面,实现类方法具备开启事务的能力。

spring在第一次使用数据库连接的时候,会从连接池中获取一个connect连接,开启事务,然后存起来,直到方法结束的时候提交事务。那么中间使用到数据连接的时候,不管是在当前方法还是在事务传递的方法,从缓存中获取这个连接,执行数据库操作。当这个事务中出现执行时间较长的业务的时候,就会出现数据库连接一直被占用而不释放。

最直接的优化方式就是watch检查哪些代码是消耗时间多的,并优化这块代码,提高接口的访问效率。
如果业务优化空间不大了,那么可以考虑对缩小事务范围,对于一个接口而言,就是最后才做事务的开启并做数据库数据修改。这里涉及到几个可能,第一是业务全过程中穿插存在数据库update操作,第二是业务前面流程只有select操作,后半段才有数据库update操作,第三是业务前半段流程操作与数据库无关,最后执行数据库update操作。(这里说的update包括insert,update,delete),总体而言优化的方向就是尽量将select或者与数据库无关的操作提前,然后数据库update操作抽离并独立开启事务,这样就能避免长时间占用数据库连接。

最后

如果觉得有用,请关注并收藏,方便以后查阅。(* ̄︶ ̄)


原文地址:https://blog.csdn.net/weixin_45149147/article/details/142492155

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!