mysql 并发 脏读_数据库并发导致的脏读 不可重复读 幻读的处理方法

修正

2020-04-23 之前是刚参加工作的理解 很多问题,现在回来重新梳理

事物的特性

原子性

表示一个最小的逻辑单元,要么都执行 要么都不执行

一致性

事物处理前与处理后的状态的要是一致的(a账户有200元 b账户有300元   共计500元  a账户给b账户转账100元。事物处理后2个账户总额也为500元)

隔离性

每个事物都有自己的数据空间,使事物的处理结果不会被别的事物所影响

持久性

事物提交 数据就永久的保存下来了

事物的隔离级别

Read uncommitted(读未提交)

会导致脏读,我们举例一个下单场景:

1.商品编号:a1的库存是10。a用户下单购买了10个商品,库存变成了10

2.a用户因为地址拍错执行退货操作:退货分为 1.开启事物 2.订单状态改为取消,3.库存还原 4.执行其他业务逻辑 5.提交事物

3.在执行 2.4的其他业务逻辑的时候 b.用户发现库存有10 执行购买 并提交事物,后续a用户退货操作因为某些操作失败 事物回滚,导致超卖

扣除库存代码

public booleanreduceStock(Long id,Long purchaseCount){

ProductStock productStock=ProductStockDao.findById(id);if(productStock.getCount()

}//库存充足

productStock.setCount(productStock.getCount()-purchaseCount);

ProductStockDao.update(productStock);return true;

}

Read committed  读取已经提交的

sqlserver默认的隔离级别,因为当前事物只能读取其他数据已经提交的数据,所以我们上面例子 第3步会校验库存不足

其实这里并发还是会超卖

比如10个用户都下单10  并发都同时走到 if(productStock.getCount()

建议通过加锁,或者sql控制如:

public boolean reduceStock(Long id,LongpurchaseCount){int updated= productStockDao.execute("update product_stock set count=count-:purchaseCount where count-:purchaseCount>=0 and id=:id",purchaseCount,id);return updated>0;

}

版本号乐观锁

public boolean reduceStock(Long id,LongpurchaseCount){

ProductStock productStock=ProductStockDao.findById(id);

String newVersion=productStock.getVersion()+1;int updated= productStockDao.execute("update product_stock set count=count-:purchaseCount,version=:newVersion where id=:id and version=:version",purchaseCount,newVersion,id,productStock.getVersion());returnupdated>0;

}

第一种适合数值的扣除,第二种适合数据修改(体验不是很好)

此隔离级别,可以解决我们的脏读但是会出现不可重复读

如:

1.查询用户性别

2.如果性别是null 则update set为男

3.再次查询并返回用户性别

在第三这个步骤时,用户性别被其他用户改成了女  返回女

Repeatable read  可重复读

可以解决重复读问题,因为这个隔离级别读取的是快照,同时update的时候会加x 事物没提交前别的事物不能修改 但是会出现幻读

如:

查询a用户的消费总额

select sum(money) from pay_log where userId=a  第二次查询的时候 log表又增加了一条数据,导致幻读

注:网上都是这样说 我的理解因为有gap锁其他事物也不能添加 我觉得这个隔离级别也可以一定程度避免幻读

Serializable 序列化

这个隔离级别最高 能够避免 脏读 不可重复读 幻影读  但是效率低(当进行当前读的时候 是锁表 性能差)

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值