有关mysql db事务隔离级别的一次实践及理解

订单在线处理系统要增加计算器功能,统计商品销量并设置订单佣金。累加和计算两步操作需保持一致性,初步考虑将多步骤包装成分布式事务,后思考仅对累加进行事务处理。利用db事务机制保证两张表一致性,还提及并发幻读及主键冲突的处理,理论上由mysql隔离机制保证行级锁。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

面临的课题

订单在线处理系统需要增加一个计算器功能,统计某个商品的销量,然后根据商品的渠道销量设置当前这笔订单的佣金。
订单关键字段:tradeId,itemId,quantity

难点分析:

累加和计算这2个步骤都有可能抛异常,这两步操作整体要保持一致性,计算需要依赖于当前累加的结果。

 

如何解决

初步思路:

累加和计算必须保证原子性,要么一起成功,要么一起失败。即:如果累加成功,计算异常了,需要一起回滚。
再仔细思考一下,这样不仅仅是2个步骤要包装成一个分布式事务,下面很多后续步骤都需要整合在一起(因为他们都可能发生异常)。分布式事务的范围肯定越小越好,因此考虑是否可以只把累加进行事务的处理。

再思考:
如果累加成功,计算异常了,认为累加“占坑”成功,不回滚;
然后需要保证后续计算的重试一定可以成功(超过重试次数,记录日志人工进行处理)。

存储结构:

表1:itemId,tradeId,curr_count(用来作为是否处理过得依据、以及重试时要拿到之前的count)

表2:itemId,sum_count(全局的数量)

note:利用db的事务机制(实现时使用注解@Transaction),保证这2张表的一致性。

 

解法:

事项加锁备注
begin 

 

1、查询表1获取当前的总数
select curr_count from table1
 

幂等,防止并发问题,

即如果已经存在,则直接返回当前的count。

2、查询表2获取当前的总数
select sum_count from table2
  
3、更新当前表2的数据 
update table2 set sum_count=sum_count+n
where sum_count=xxx
update 加锁

mysql 事务乐观锁机制

4、插入当前表1的数据
insert into table1 (itemId, tbTradeId, sum_count)
insert加锁 
commit释放锁 

 

note:
如果并发(两条相同消息同时到达)导致幻读,insert会抛异常,这个时候上游触发重试即可。
也可以捕获主键冲突的异常,进行额外的处理。

 

理论支撑

整体db层面的行级锁由db的隔离机制来保证,
mysql的事务默认隔离级别是 Repeatable Read(可重读)。

详细可见:深入理解Mysql的四种隔离级别

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值