MySQL系列---隔离级别与存储引擎

本文探讨了MySQL的事务隔离级别和存储引擎,强调了不必要时不应过度使用锁,解释了脏写的概念,并分析了不同存储引擎如MyISAM和InnoDB的特点。在事务隔离级别方面,说明了其只针对读操作,如脏读、幻读和不可重复读等问题,以及如何通过MVCC机制避免这些问题。此外,文章还提到了数据库死锁的处理方式,包括等待超时和死锁检测机制。
摘要由CSDN通过智能技术生成

在15+2项目中由于使用redis分布式锁时加完锁忘记删锁而导致的一段故事,进而深入思考。

加锁不是一件好事,加锁时一定要慎之又慎,如果可以用逻辑处理并发影响或者依赖数据库处理那么就不要加锁,加锁对性能的影响极大,如果没有感受到影响,无他,并发量太小未达到瓶颈罢了,加锁的影响无论何时何地都是切实存在的。
判断是否加锁的唯一标准:并行时会不会造成数据错误
个人历程,从最开始的不加锁,到加锁,再到滥用锁,再到精准用锁,最后到锁合并。

  1. 不加锁,最开始没有加锁,导致了二维码的重复使用,还导致了用户流水的加减错误(虽然也有可能是排序的问题,datetime的精度太低,但未加锁的原因最大)
  2. 使用锁,二维码限制住了,流水加减错误限制住了,(虽然自创的控制码的锁有各种各样的问题,优化了n个版本,也不知道现在这个怎么样,就是为了判断锁里面的值,减少一次mysql读取)
  3. 滥用锁,海报模块中由于加完锁之后忘记解锁,导致了一系列的问题,海报锁未删除–》人锁未删除–》mysql数据死锁(事务未提交,废话,一直有锁咋提交事务);加上所删除之后,不禁思考为什么会导致这么严重的后果,就是因为加的锁太多了,一段代码中一下加了三个锁,码锁、user锁、source锁、导致一个锁未删除,则产生连带效果,一发不可收拾。
  4. 精简锁,如果不是必须禁止用锁,也就说当并行时不会造成数据混乱或者逻辑混乱。
    消费者领取海报时,一下加了三个锁,海报锁、user锁、source锁,其实仔细想想,user根本不需要加锁啊,海报的流水时单独计算的,并且不参与累计,那么为什么要对user加锁?user锁被滥用
    消费者核销海报时,同样加了三个锁,海报锁、user锁、source锁,分析一下,海报锁已经由mysql计算了,加不加无所谓,user流水单独记录,更是不需要加!!user锁和海报锁被滥用。
  5. 锁合并,在思考锁时突然反应过来,红包回调时如果用户刚好在领取红包,那么其实会导致数据混乱的,也就说红包奖的控制和饮料奖的控制应该是两个控制,然后正准备再加上一个红包奖的锁,突然发现我锁的是人,也就是说以人为维度进行加锁,领取饮料、领取红包、回退红包、核销饮料、兑换饮料时,其实就都用的一个锁,这5件事只能存在一个,虽然锁的粒度大了,但是少了一个锁,并且也拆不开,因为额外奖励和定向奖励的存在,红包和饮料已经掺和在了一起,没办法分开,只能这样加锁,也算是歪打正着。

无必要不加锁,粒度越细越好,个数越少越好。

1. 老生常谈

以为优化好的锁:

rqrcodekey = JmlRedisKey.LOCK_QRCODE.concat(qrcode);
Boolean rqrcoderesB = redisUtils.redLock(rqrcodekey,JmlConstant.Properties.DOING,rkeyTime);
if(!rqrcoderesB) {
   
    String rqrcoderes = (String) redisUtils.get(rqrcodekey);
    logger.info("箱码发生码同步1:{}",rqrcoderes);
    if (rqrcoderes == null || StrUtil.isBlank(rqrcoderes) || rqrcoderes.equals(JmlConstant.Properties.FAILED)) {
   
        redisUtils.set(rqrcodekey, JmlConstant.Properties.DOING, rkeyTime);
    } else if (rqrcoderes.equals(JmlConstant.Properties.SUCCESS)) {
   
        return new ResponseBean<>("401", "该码已使用过", "该码已使用过");
    } else if (rqrcoderes.equals(JmlConstant.Properties.DOING)) {
   
        while (rqrcoderes.equals(JmlConstant.Properties.DOING)) {
   
            Thread.sleep(sleepTime);
            rqrcoderes = (String) redisUtils.get(rqrcodekey);
            logger.info("箱码发生码同步2:{}",rqrcoderes);
            if (rqrcoderes == null || StrUtil.isBlank(rqrcoderes) || rqrcoderes.equals(JmlConstant.Properties.FAILED)) {
   
                redisUtils.set(rqrcodekey, JmlConstant.Properties.DOING, rkeyTime);
                break;
            }else if(rqrcoderes.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lipviolet

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值