MySQL更新的常见问题

一、“丢失更新”

一个事务的更新操作被另外一个事务的更新操作覆盖。在RR状态下,普通select的时候是会获得旧版本数据的,但是update的时候就检索到最新的数据。


解决方法:在读取的过程中设置一个排他锁,在 begin 事务里, select 语句中增加 for update 后缀,这样可以保证别的事务在此事务完成commit前无法操作记录。参考《MySQL技术内幕 InnoDB存储引擎》

二、减库存的场景

当前库存:num=200
假如多线程并发:
AB同时开启事务,A先请求到行锁,
A:
start transaction;
select num from t where num>0;先查询当前库存值(num>0)
update t set num=num-200; 库存减量

B:
start transaction;
select num from t where num>0;先查询当前库存值(num>0)
update t set num=num-200; 库存减量
----结果---
A:查询到num=200,做了库存减量成了0
B:事务启动后,查询到也是200,等 A 释放了行锁,B进行update,直接变成 -200
但是 B 查询时,时有库存的,因此才减库存,结果变成负的。
老师,对于这种场景,怎么避免减成负值?
给 select 加读锁或者写锁吗 ?这种select 加锁,对业务影响大吗?

答:

一开始Select 加锁虽然可以,但是会比较严重地影响并发数。

比较简单的做法是update语句的where 部分加一个条件: where nun >=200 .
然后在程序里判断这个update 语句的affected_rows, 
如果等于1 那就是符合预期;
如果等于0,那表示库存不够减了,业务要处理一下去,比如提示“库存不足”

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值