记一次长事务方法带来的坑

1. 沟通需求

产品找到我说,咱要将一波数据给更新了,因为涉及业务,就不说具体的内容了,需要支持分页滚动,校对数据后进行推送,大致是需要几万条的明细数据构建出一张大订单,要么同时成功或者失败。

2.分析需求

所以需要实现两个需求,一个是查询分页返回合计信息,第二个是点击确认进行推送。

我一想不是很简单嘛,就立马动手做了,搞个分页,然后让前端滚动合计金额值。

在这里插入图片描述

确认接口直接调用原来的就好。

3. 波折起

于是调试的时候就发现问题了,通过分页的方式,虽然快速返回了数据,但页数很多,到最后推送的时候,还是要让他将最后合计的几万条明细数据推给我,这不就是要查询全部嘛。
在这里插入图片描述

好吧,那只能一次给他返回全部了,合计金额也我来算。

4.初版完成

这样数据勉强能返回了,推送的时候他将数据都给我,我丢到mq里进行处理,由于数据量很大,我只能在接收到数据的时候放到oss中,mq消费的时候再拿出来,这样倒是还行。

但后面前端说不能传那么大的参数,我说那行吧,把query传过来,mq消费后分页查询,再做更新,就这样,初版程序完成了。
在这里插入图片描述

5.锁等待超时

由于我这是一个长事务的操作,每次推送几万条数据得半小时,这样就会有长时间的事务锁行,好在插入的数据比较多,但中间有一个更新操作,每次循环都更新几千条数据,而中途可能会有别人的操作某些行,于是操作就失败了,报错如下。

 java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction
; Lock wait timeout exceeded; try restarting transaction; nested exception is java.sql.BatchUpdateException: Lock wait timeout exceeded; try restarting transaction 

在这里插入图片描述

我一查发现是等待锁超时导致的,似乎有个其他的操作的长事务,锁住了某几行数据长达50s,我的更新操作等待就超时了。

好吧,我想到了可以将这大量的更新操作放在所有操作的最后面,这样该操作的占用时间少,比之前的占锁时间少很多。

然后我再添加一个重试机制,不是别的操作占用锁了嘛,我就失败了,等个几秒钟,把异常捕获下,再重试下进行更新,当然,具体的操作我会将异常更新的集合记录下来,先更新其他分组的,最后再统一分组处理。

6.消费者超时

我不是使用了mq嘛,一般处理消息都是快的,但某次消费消息超过了半小时,就给我报了这样的错。

 [2.16.10.43:5672] o.s.a.r.c.CachingConnectionFactory       : Channel shutdown: channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILED - delivery acknowledgement on channel 1 timed out. Timeout value used: 1800000 ms. This timeout value can be configured, see consumers doc guide to learn more, class-id=0, method-id=0)

在这里插入图片描述

我一查,好吧,消费者超时,默认消费者的超时时间是30分钟,但我不好改公司的全局配置,且超时时间不好确认,我只好将消息提前确认了。

这样带来的坏处是,一旦服务器重启,那这个任务就会中断,但也好解释,都重启了嘛,让客户之后再操作下,反正有事务控制的。

7.总结

这算是一个折中的方案,暂时先这么用着,起码能保证功能先用着,现实情况往往都是如此,你不可能做的很完美,只能做出权衡利弊后的应对措施。

且很多时候不能从技术方面考虑怎么做,其实是产品设计的有问题,他想的太简单了,应该从功能上进行优化,哎,应该好好沟通来着,给自己埋坑了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值