zoukankan      html  css  js  c++  java
  • 什么是间隙锁

    此文转载自:https://blog.csdn.net/qq_21729419/article/details/113643359#commentBox

    中心思想

    间隙锁锁的是索引叶子节点的next指针。

    意义

    解决了mysql RR级别下是幻读的问题。

    快照读

    在RR隔离级别下:快照读有可能读到数据的历史版本,也有可能读到数据的当前版本。所以快照读无需用锁也不会发生幻读的情况。

    当前读

    当前读:select…lock in share mode,select…for update
    当前读:update,delete,insert

    读取的是记录的最新版本,所以所以就需要通过加锁(行锁 间隙锁 表锁)的方式,使得被当前读读过的数据不能被新增修改或者删除,换句话说再来一次当前读要返回相同的数据。

    为什么需要间隙锁

    数据表

    CREATE TABLE `z` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `b` int(11) DEFAULT NULL,
      `c` int(255) NOT NULL DEFAULT '0',
      PRIMARY KEY (`id`),
      KEY `b` (`b`)
    ) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8;
    
    
    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('1', '1', '0');
    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('3', '6', '1');
    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('5', '4', '2');
    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('7', '8', '3');
    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('8', '10', '4');
    
    

    索引B结构

    锁加在哪里

    begin; select * from z where b = 6 for update;

    这条sql语句之后看看我们 需要做什么才能保证不发生幻读。

    1不能插入b为6的数据

    2不能删除b为6的数据

    3不能修改b为6的数据

    4不能把别的数据修改为b为6

    突然一看挺复杂的,这个锁要怎么加呢,mysql大牛灵机一动,给叶子节点5的next指针加锁,给叶子节点3加行锁,给叶子节点3的next指针加锁。如下图所示

    这样不就能把上述四个问题解决了么,两个next指针锁解决了插入b为6或者把别的数据修改为b为6,行锁解决了修改b为6的行,但是呢也带来一些明显的副作用。

    例如

    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('6', '4', '0'); 

     会bolck因为按照索引结构这条数据会插入到叶子结点5和3之间,会修改叶子节点5的next指针,虽然这条sql没有破坏上述的4个红色条件但是依然被阻塞了所以我叫它为副作用。

    INSERT INTO `study`.`z` (`id`, `b`, `c`) VALUES ('4', '4', '0'); 

     插入成功因为这条数据会插入在1的后面5的前面。

    现在大家是不是能理解间隙锁的怪异行为了呢。

    间隙锁范围

    begin; 
    select * from z where id=4 for update;

    会锁住主键索引叶子节点的3的next指针。(为啥呢,需要你自己画主键索引的图)

    begin; 
    select * from z where id=3 for update;

    间隙锁会退化为行锁只锁叶子节点3 ,为什么因为没必要。不加间隙锁也不会打破上述的红色4个条件。

    begin; 
    select * from z where id>4 for update;

    叶子节点3及之后所有节点会加行锁并且他们的next指针会加锁,

    begin; 
    select * from z where c=2 for update;

    会发生锁表,因为c没有索引结构能存储行锁或者间隙锁。

       

    更多内容详见微信公众号:Python测试和开发

    Python测试和开发

  • 相关阅读:
    C++实现二叉树的相应操作
    C++对文件的操作
    C++与C的区别二
    C++多线程编程二
    C++多线程编程一
    C语言多线程编程二
    C语言多线程编程一
    HTML练习(三)
    磁盘/内存模式查询数据
    RestTemplate使用不当引发的问题分析
  • 原文地址:https://www.cnblogs.com/phyger/p/14377651.html
Copyright © 2011-2022 走看看