1商品的库存原本有100件,老板又进了50件货,一个小时后卖出了30件。此时小李和小王同时操作后台系统,小李操作的时候先取出库存100;小王也在操作,取出的库存也是100.小李将库存加了50,将结果100+50写入数据库;小王将库存减了30,并将100-30写入数据库。因为没有上锁,小李的操作完全被小王覆盖了
。现在的库存是70,对不上账了。
乐观锁与悲观锁,
如果是乐观锁,会检查一下库存是否被被人修改过了,如果修改过了会重新获取修改后的的库存。
如果是悲观锁,只有等到别人操作完成了,才能进行操作。
-- auto-generated definition
create table goods
(
id int auto_increment comment '商品id'
primary key,
name varchar(30) null comment '商品名称',
stock int default 0 null comment '商品库存',
version int default 0 null comment '并发版本控制'
)
comment '商品表' charset = utf8;
@Test
public void test_currentUpdate() {
Goods good1 = goodsMapper.selectById(1);
Goods good2 = goodsMapper.selectById(1);
good1.setStock(good1.getStock() + 50);
goodsMapper.updateById(good1);
good2.setStock(good2.getStock() - 30);
int result = goodsMapper.updateById(good2);
if (result == 0) {
Goods p2 = goodsMapper.selectById(1);
p2.setStock(p2.getStock() - 30);
goodsMapper.updateById(p2);
}
//最后的结果
Goods goods3 = goodsMapper.selectById(1L);
System.out.println("最后的结果:" + goods3.getStock());
}
image.png
取出数据时获取当前的version,更新的时候比较version 如果version不对,更新失败。
UPDATE goodsSET stock=stock+50, `version`=`version` + 1 WHERE id=1 AND `version`=1
public class Goods implements Serializable {
private static final long serialVersionUID = 1L;
/**
* 商品id
*/
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
/**
* 商品名称
*/
private String name;
/**
* 商品库存
*/
private Integer stock;
/**
* 并发版本控制
*/
@Version
private Integer version;
}
加了version注解后
image.png
网友评论