@Transactional导致的生产事故
当我们遇到一个长事务的时候,尽量不要是用@Transactional注解
因为当高并发的时候可能出现:数据库监控平台一直收到告警短信,数据库连接不足,出现大量死锁;日志显示调用流程引擎接口出现大量超时;同时一直提示CannotGetJdbcConnectionException,数据库连接池连接占满。
原因:当 Spring 遇到该注解时,会自动从数据库连接池中获取 connection,并开启事务然后绑定到 ThreadLocal 上,对于@Transactional注解包裹的整个方法都是使用同一个connection连接。如果我们出现了耗时的操作,比如第三方接口调用,业务逻辑复杂,大批量数据处理等就会导致我们我们占用这个connection的时间会很长,数据库连接一直被占用不释放。一旦类似操作过多,就会导致数据库连接池耗尽。
何为长事务?
顾名思义就是运行时间比较长,长时间未提交的事务,也可以称之为大事务。
长事务会引发哪些问题?
长事务引发的常见危害有:
(1)数据库连接池被占满,应用无法获取连接资源;
(2)容易引发数据库死锁;
(3)数据库回滚时间长;
(4)在主从架构中会导致主从延时变大。
如何避免长事务?
既然知道了长事务的危害,那如何在开发中避免出现长事务问题呢?
很明显,解决长事务的宗旨就是 对事务方法进行拆分,尽量让事务变小,变快,减小事务的颗粒度。
既然提到了事务的颗粒度,我们就先回顾一下Spring进行事务管理的方式。
基于底层的API,开发者在代码中手动的管理事务的开启、提交、回滚等操作。在spring项目中可以使用TransactionTemplate类的对象,手动控制事务。
@Autowired
private TransactionTemplate transactionTemplate;
...
public void save(RequestBill requestBill) {
transactionTemplate.execute(transactionStatus -> {
requestBillDao.save(requestBill);
//保存明细表
requestDetailDao

本文探讨了@Transactional注解在高并发场景下可能导致的数据库连接池耗尽、死锁等问题,详细阐述了长事务的概念及其引发的危害,如连接资源耗尽、数据库回滚时间长等。建议通过拆分事务方法、使用编程式事务等方式避免长事务,提高事务处理效率和系统的稳定性。
最低0.47元/天 解锁文章
2145

被折叠的 条评论
为什么被折叠?



