程序员子龙(Java面试 + Java学习) 程序员子龙(Java面试 + Java学习)
首页
学习指南
工具
开源项目
技术书籍

程序员子龙

Java 开发从业者
首页
学习指南
工具
开源项目
技术书籍
  • 基础

  • JVM

  • Spring

  • 并发编程

  • Mybatis

  • 网络编程

  • 数据库

    • MySQL

      • 安装mysql
      • Mybatis查询数据部分字段显示为null,转换成”“
      • 一文搞懂MySQL索引
      • 史上最全MySQL各种锁详解
      • 间隙锁
        • 死锁
        • mysql索引为啥使用B+tree?
        • Mysql Explain工具介绍
        • MVCC
        • MySQL事务【详解-最新的总结】
        • 「数据库、数据库连接池、数据源」这些概念你真的理解了吗?
        • Mysql慢查询及优化(全网最详细!!!)
        • MySQL锁、加锁机制(超详细)—— 锁分类、全局锁、共享锁、排他锁;表锁、元数据锁、意向锁;行锁、间隙锁、临键锁;乐观锁、悲观锁
        • MySQL事务(超详细!!!)
      • Oracle

      • iotdb

      • Mongodb

    • 缓存

    • 设计模式

    • 分布式

    • 高并发

    • SpringBoot

    • SpringCloudAlibaba

    • Nginx

    • 面试

    • 生产问题

    • 系统设计

    • 消息中间件

    • Java
    • 数据库
    • MySQL
    程序员子龙
    2024-01-29
    目录

    间隙锁

    间隙锁,锁的就是两个值之间的空隙。Mysql默认级别是repeatable-read,间隙锁在某些情况下可以解决幻读问题。间隙锁属于行锁中的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间,遵循左开右闭原则。

    准备表

    CREATE TABLE `account` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `name` varchar(255) DEFAULT NULL,
      `balance` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=1
    
    1
    2
    3
    4
    5
    6

    准备数据

    INSERT INTO `account` VALUES (1, 'lilei', 450);
    INSERT INTO `account` VALUES (2, 'hanmei', 16000);
    INSERT INTO `account` VALUES (3, 'lucy', 2400);
    INSERT INTO `account` VALUES (10, 'liuda', 1000);
    INSERT INTO `account` VALUES (20, 'zhaosi', 2000);
    
    1
    2
    3
    4
    5

    那么间隙就有 id 为 (3,10),(10,20),(20,正无穷) 这三个区间,那么间隙锁有(-∞,3](3,10](10,20](20,+∞]

    # 案例一

    开启一个事务

    #手动提交
    SET autocommit = 0;
    BEGIN;
    
    update account set name = 'kongming' where id > 8 and id <18;
    
    1
    2
    3
    4
    5

    此时没有提交事务。

    开启另外一个事务

    SET autocommit = 0;
    BEGIN;
    #阻塞
    INSERT INTO `account` VALUES (7, 'laohuang', 3000);
    #阻塞
    update account set balance = 5000 WHERE id = 20;
    
    #可以执行成功
    INSERT INTO `account` VALUES (21, 'laosong', 3000);
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    可以看出,事务1没有提交,则其他事务没法在这个范围所包含的所有行记录(包括间隙行记录)以及行记录所在的间隙里插入或修改任何数据,即id在(3,20]区间都无法修改数据,注意最后那个20也是包含在内的。

    间隙锁是在可重复读隔离级别下才会生效。

    # 案例二

    #事务一
    SET autocommit = 0;
    BEGIN;
    
    update account set balance = 10000 WHERE id = 11;
    
    
    1
    2
    3
    4
    5
    6

    事务一没有提交。

    #事务二
    SET autocommit = 0;
    BEGIN;
    #阻塞
    INSERT INTO `account` VALUES (12, 'laohuang', 3000);
    
    
    COMMIT;
    
    1
    2
    3
    4
    5
    6
    7
    8

    事务二会阻塞。

    步骤 事务A 事务B
    begin; begin;
    1 update account set balance = 10000 WHERE id = 11; -
    2 - INSERT INTO account VALUES (12, 'laohuang', 3000);\color{red}{blocked}
    3 commit; -

    事务一会对数据库表增加(10,20]这个区间锁,这时insert id = 12 的数据的时候就会因为区间锁(10,20]而被锁住无法执行。

    上次更新: 2024/01/30, 15:08:57
    史上最全MySQL各种锁详解
    死锁

    ← 史上最全MySQL各种锁详解 死锁→

    最近更新
    01
    一个注解,优雅的实现接口幂等性
    11-17
    02
    MySQL事务(超详细!!!)
    10-14
    03
    阿里二面:Kafka中如何保证消息的顺序性?这周被问到两次了
    10-09
    更多文章>
    Theme by Vdoing | Copyright © 2024-2024

        辽ICP备2023001503号-2

    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式