Springboot @Transactional大事务处理的几点建议
作者:哈喽,树先生
本文主要介绍了大事务的概念及其危害,并提出了几种解决大事务问题的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
1.大事务:
总体任务对应的事务运行时间比较长,长时间未提交的事务。
2.大事务的危害:
a.并发情况下,数据库连接池资源占满。大事务提交不及时,导致连接资源释放缓慢。
b.数据库死锁和锁等待。mysql innodb存储引擎背景下,事务如果占用了排他锁,会容易导致并发情况下数据死锁或者锁等待。
c.大事务Rt时间长,容易导致接口超时。
d.大事务回滚时间长。
e.数据库主从架构下,数据同步延迟
3.解决办法
3.1 将声明式事务的@Transactional方式 合理的替换为 编程式事务TransactionTemplate 的方式
声明式事务的粒度最小是整个方法,可能会导致业务里不必要的逻辑都加了事务。编程式事务细化需要加事务的逻辑上,形成实际有用的事务块。
@Autowired private TransactionTemplate transactionTemplate; public void testTransaction() { transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { try { // .... 业务代码 } catch (Exception e){ //回滚 transactionStatus.setRollbackOnly(); } } }); }
3.2 将查询放在事务方法外
使用@Transactional 又想避免产生大事务,需对方法进行拆分,将不需要事务管理的逻辑与事务操作分开
@Service public class TransactionTestService{ // 避免同一个类内部方法相互调用,实例方法调用代理方法而导致事务失效 @Resource private TransactionTestService service; public void create(ParamDto dto){ queryData1(); queryData2(); service.save(dto); } //事务操作 @Transactional(rollbackFor = Exception.class) public void save(ParamDto dto){ paramDao.insert(dto); } }
3.3 避免跨服务间的远程调用
服务间的通讯及服务之间的调用时间 受网络环境和远端接口Rt时间的影响,可能会比较耗时。
反例: //事务操作 @Transactional(rollbackFor = Exception.class) public void save(ParamDto dto){ // 调用了其他服务 otherRemoteApi(); paramDao.insert(dto); } 修改为: @Autowired private TransactionTemplate transactionTemplate; public void save(ParamDto dto){ // 调用了其他服务 otherRemoteApi(); transactionTemplate.execute(new TransactionCallbackWithoutResult() { @Override protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) { try { paramDao.insert(dto); } catch (Exception e){ //回滚 transactionStatus.setRollbackOnly(); } } }); }
3.4 事务中不应该一次性处理太多的数据,可以使用分批执行
3.5事务中的方法可以根据业务使用异步执行
到此这篇关于Springboot @Transactional大事务处理的几点建议的文章就介绍到这了,更多相关Springboot @Transactional大事务内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!