zoukankan      html  css  js  c++  java
  • mysql间隙锁 转

    前面一文 mysql锁 介绍了mysql innodb存储引擎的各种锁,本文介绍一下innodb存储引擎的间隙锁,就以下问题展开讨论

    1.什么是间隙锁?间隙锁是怎样产生的?

    2.间隙锁有什么作用?

    3.使用间隙锁有什么隐患?

    一、间隙锁的基本概念

    1.什么叫间隙锁

    当我们用范围条件而不是相等条件检索数据,并请求共享或排他锁时,InnoDB会给符合条件的已有数据记录的索引项加锁;对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁,这种锁机制就是所谓的间隙锁(NEXT-KEY)锁。

    2.间隙锁的产生

    上面的文字很抽象,现在举个栗子,介绍间隙锁是怎么产生的:

    假设有以下表t_student:(其中id为PK,name为非唯一索引)

    id name sex address
    1 zhaoyi 0 beijin
    3 sunsan 1 shanghai
    4 lisi 0 guangzhou
    5 zhouwu 0 shenzhen
    6 wuliu 1 hangzhou

    这个时候我们发出一条这样的加锁sql语句:

    select id,name from t_student where id > 0 and id < 5 for update;

    这时候,我们命中的数据为以下着色部分:

    id name sex address
    1 zhaoyi 0 beijin
    3 sunsan 1 shanghai
    4 lisi 0 guangzhou
    5 zhouwu 0 shenzhen
    6 wuliu 1 hangzhou

    细心的朋友可能就会发现,这里缺少了条id为2的记录,我们的重点就在这里。

    select ... for update这条语句,是会对数据记录加锁的,这里因为命中了索引,加的是行锁。从数据记录来看,这里排它锁锁住数据是id为1、3和4的这3条数据。

    但是,看看前面我们的介绍——对于键值在条件范围内但不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个“间隙”加锁。

    好了,我们这里,键值在条件范围但是不存在的记录,就是id为2的记录,这里会对id为2数据加上间隙锁。假设这时候如果有id=2的记录insert进来了,是要等到这个事务结束以后才会执行的

    二、间隙锁的作用

    总的来说,有2个作用:防止幻读和防止数据误删/改

    1.防止幻读

    关于幻读的概念可以参考我这篇文章 https://blog.csdn.net/mweibiao/article/details/80805031 ,这里就不多做解释了

    假设有下面场景

    时间 事务A 事务B
    T1 select count(1) from t_student where id > 1;  
    T2   insert into t_student values(2,'qianer',1,'nanjing');
    T3   commit;
    T4 select count(1) from t_student where id > 1;  
    T5 commit;  

    如果没有间隙锁,事务A在T1和T4读到的结果是不一样的,有了间隙锁,读的就是一样的了

    2.防止数据误删/改

    这个作用比较重要,假设以下场景:

    时间 事务A 事务B
    T1 delete from t_student where id < 4;  
    T2   insert into t_student values(2,'qianer',1,'nanjing');
    T3   commit;
    T4 commit;  

    这种情况下,如果没有间隙锁,会出现的问题是:id为2的记录,刚加进去,就被删除了,这种情况有时候对业务,是致命性的打击。加了间隙锁之后,由于insert语句要等待事务A执行完之后释放锁,避免了这种情况

    三.使用间隙锁的隐患

    最大的隐患就是性能问题

    前面提到,假设这时候如果有id=2的记录insert进来了,是要等到这个事务结束以后才会执行的,假设是这种场景  

    时间 事务A 事务B
    T1 select * from t_student where id>1 and id < 100 for update;  
    T2   insert into t_student values(2,'qianer',1,'nanjing');
    T3 update t_student set xxxx where id=xxx;  
    T4 update t_student set xxxx where id=xxx;  
    T5 update t_student set xxxx where id=xxx;  
    T6  
    T7 commit;  

    这种情况,对插入的性能就有很大影响了,必须等到事务结束才能进行插入,性能大打折扣

    更有甚者,如果间隙锁出现死锁的情况下,会更隐晦,更难定位

    原文 https://www.cnblogs.com/billmiao/p/9872161.html

  • 相关阅读:
    Alpha冲刺(5/10)
    Alpha冲刺(4/10)
    团队现场编程
    关于合同标准形的专题讨论
    关于相似标准形的专题讨论
    关于数学分析的计算题I(积分)
    关于数学分析的证明题III(级数)
    关于数学分析的证明题II(微分)
    关于数学分析的证明题I(积分)
    关于反常积分收敛的专题讨论
  • 原文地址:https://www.cnblogs.com/brady-wang/p/13258745.html
Copyright © 2011-2022 走看看