• mysql 学习日记 悲观和乐观锁


    理解  悲观锁就是什么事情都是需要小心翼翼,生怕弄错了出大问题,

    一般情况下 "增删改" 都是有事务在进行操作的,但是 "查" 是不需要事务操作的,

    但是凡事没有例外,比如双十一购物,很多人抢购一个物品,但是商品总数(假设5个)

    同一时间进行操作,每个人都能看到物品多少个,都早同一时间下单,但是只有5个商品,只有5个用户能过购买到(每人一个购买),其他人也会显示出订单的操作,但是库存已经是为0无法购买的行为(显示还是5ge库存),会给用户造成不好体验

    既让如此 为什么不让一个事务锁定物品的个数修改,而其他用户只能查看,并不能下单,当用户进行updata操作之后释放锁,其他用户才能根据情况下单,再次把物品行锁住(不会出现订单表交钱了还提示没库存)

    可能我说的不是很准确,但是悲观锁就是一步一步走,如果轮到它则执行则锁行操作,避免一些问题,一般用在金钱询,库存询等... 

    执行sql语句格式

    select money from usercred where id=1 for update;

    统一格式在select查询条件之后增加 for updata (记住查询条件是索引列才是锁行不让则是锁表)            查询操作中除了敏感数据查询,其他不需要使用锁行操作

    总体理解就是 悲观锁是一个在有需要求的情况下查询语句事务中隔离性最高的ser...  串行,当悲观锁锁住行时,其他事务只能等待,并且不能读取该行悲观数据

    并且悲观锁只能在begin和commit之间执行




    乐观锁 查询出需要修改的数据,但是增加一个字段作为一个版本控制(像git一样),如果进行修改一起将版本控制的字段一起where作为条件,如果符合则修改,不符合也没事,因为数据库中的数据给其他事务修改之后,where查询的条件不符合,所以不会对持久化的数据造成影响

    例子如下

    create table card(
       id int;
       money float;
       version int;                        // 乐观锁控制,字段名无所谓
       primary key(id);                 // 主键
       auto increment(id);             // 自增长
       index(money,version);         // 索引
    );        

    创建上面一个表,我使用go的gorm来表达一下操作

    type card struct{
        Id int                       `gorm:"id"`
        Money float              `gorm:"money"`     // 默认这个账户100元
        Version int               `gorm:"varsion"`
    }
    
    func main(){
        var c card
        if err := db.first(&c).Error():err!=nil{       // 查出一条数据
              panic(err)
        }
        err = db.Model(&c).Where("id = ? and varsion = ?",c.Id,c.Version).updata(c.Money + 200 ,c.Version+1).error()
       if err != nil{
             // 说明其他事务在我执行这个操作时进行了updata commit,我这边where在数据查询表没有出现符合条件的,所以执行失败
        }
        fmt.Println("success")
    }    

    乐观锁就不是一个事务的操作,是手动创建的一种逻辑来保证数据一致性

    根据多个条件来进行控制数据是否和查询时一致保持安全

    比方  a 操作查询得到一个数据,其中返回的数据集中含有 money(100)和一个varsion(1),,你对这个数据进行修改,其中money+100,varsion+1 ,但是在你修改还没有提交时,其他b,c,d..的连接也同时和你一样的操作,并且比你提交commit的速度快,当你使用updata修改语句去根据先前查询得到结果寻找数据时,对比version和money,但是已经有其他提交比你快提交了,找不到a查询过的数据行(此时时b连接提交的数据是money = 300,version=2),所以不会提交,丢弃操作,

    乐观使用一个额外字段保证数据和查询出时的数据一致才会更新(更新查询时查询的条件要有唯一属性,不让更新查询时出现多个操作不可逆)


    悲观锁更加适合转账交易业务,乐观锁倾向并不是对数据要求绝对安全的环境,但是绝对不适用于转账交易等敏感地位

    悲观锁和事务区别在于

    悲观锁会将查询时就将行锁住,其他连接操作不能查询更不能修改,但是也是事务的一种

    事务  一般用于增删改而不用于查的事务管理(虽然也可以管理查的事务,但是和悲观锁一样差不多,除非时特别需求,不然不会要求对查的操作加锁)

  • 相关阅读:
    BZOJ4779: [Usaco2017 Open]Bovine Genomics
    USACO比赛题泛刷
    BZOJ1977: [BeiJing2010组队]次小生成树 Tree
    LOJ #10132. 「一本通 4.4 例 3」异象石
    $O(n+log(mod))$求乘法逆元的方法
    BZOJ2226: [Spoj 5971] LCMSum
    数据库 | Redis 缓存雪崩解决方案
    中间件 | 微服务架构
    数据库 | SQL 诊断优化套路包,套路用的对,速度升百倍
    数据库 | SQL语法优化方法及实例详解
  • 原文地址:https://www.cnblogs.com/zengxm/p/11651758.html
Copyright © 2020-2023  润新知