博客
关于我
MySQL 的全局锁、表锁和行锁
阅读量:799 次
发布时间:2023-02-11

本文共 2255 字,大约阅读时间需要 7 分钟。

在前一篇文章中,我已经简单介绍了MySQL的全局锁、表级锁和行级锁,其中行级锁仅仅提到了概念,但没有深入讲解。由于行级锁的加锁规则较为复杂,不同场景下加锁的形式也不同,因此本文将深入探讨行级锁的具体实现机制。

在数据库管理系统中,行级锁是最常用的锁定机制之一,其最基本的加锁单位是next-key lock。这个锁定机制由记录锁和间隙锁组合而成。具体来说,next-key lock表示的是前开后闭的区间,而间隙锁则表示前开后开的区间。

需要注意的是,在某些特定场景下,next-key lock会退化为记录锁或间隙锁。那么,这些具体的退化场景又是什么样的呢?为了更好地理解这一点,我们可以通过以下表结构和实际操作来进行实验说明。

以下是我们实验使用的表结构:

id b a
8 8 8
9 9 9
16 16 16

需要注意的是,我使用的是MySQL 8.0.26版本,由于不同版本的MySQL可能会有不同的加锁规则,这也是理解行级锁加锁机制的重要基础。

接下来,我们将从以下几个方面来分析行级锁的加锁规则:

  • 唯一索引等值查询

    • 当查询的记录存在时,next-key lock会退化为记录锁。
    • 当查询的记录不存在时,next-key lock会退化为间隙锁。
  • 非唯一索引等值查询

    • 当查询的记录存在时,除了next-key lock,还会额外加间隙锁。
    • 当查询的记录不存在时,只会加next-key lock,然后会退化为间隙锁。
  • 非唯一索引范围查询

    • 行级锁的加锁规则在非唯一索引范围查询中与唯一索引有所不同。普通索引范围查询中,next-key lock不会退化为间隙锁和记录锁。
  • 为了更直观地理解这些加锁规则,我们可以通过以下具体案例来分析。

    案例一:唯一索引等值查询

    假设我们执行以下两个更新操作:

    update t_test set a = 1 where id = 8 for update;update t_test set a = 1 where id > 8 and id < 9 for update;

    在执行这两个查询时,分别分析加锁情况:

    • 对于第一个查询update t_test set a = 1 where id = 8 for update,由于id是唯一索引且记录存在,next-key lock会退化为记录锁,锁定范围仅限于id=8这一行。

    • 对于第二个查询update t_test set a = 1 where id > 8 and id < 9 for update,由于id是唯一索引且记录不存在,next-key lock会退化为间隙锁,锁定范围为(8,16)。

    因此,会话2在尝试往间隙锁中插入id=9的记录时会被锁定,而会话3修改id=16的记录也会被锁定。

    案例二:非唯一索引等值查询

    假设我们执行以下两个更新操作:

    update t_test set a = 1 where b = 8 for update;update t_test set a = 1 where b > 8 and b < 16 for update;

    分析加锁情况:

    • 对于第一个查询update t_test set a = 1 where b = 8 for update,由于b是非唯一索引且记录存在,next-key lock会加在b=8这一行,同时还会额外加间隙锁,锁定范围为(8,16)。

    • 对于第二个查询update t_test set a = 1 where b > 8 and b < 16 for update,由于b是非唯一索引且记录不存在,next-key lock会加在b=8到b=16的范围内,但由于是普通索引,next-key lock不会退化为间隙锁,因此锁定范围为(8,16]。

    因此,会话2在尝试往间隙锁中插入b=9的记录时会被锁定,而会话3修改b=16的记录也会被锁定。

    案例三:非唯一索引范围查询

    假设我们执行以下两个更新操作:

    update t_test set a = 1 where b = 8 for update;update t_test set a = 1 where b > 8 and b < 16 for update;

    分析加锁情况:

    • 对于第一个查询update t_test set a = 1 where b = 8 for update,由于b是非唯一索引且记录存在,next-key lock会加在b=8这一行,同时还会额外加间隙锁,锁定范围为(8,16)。

    • 对于第二个查询update t_test set a = 1 where b > 8 and b < 16 for update,由于b是非唯一索引且记录不存在,next-key lock会加在b=8到b=16的范围内,但由于是普通索引,next-key lock不会退化为间隙锁,因此锁定范围为(8,16]。

    因此,会话2在尝试往间隙锁中插入b=9的记录时会被锁定,而会话3修改b=16的记录也会被锁定。

    通过以上案例可以看出,行级锁的加锁规则在不同的查询场景下表现出不同的特点。理解这些规则对于数据库的并发控制和高并发场景的优化具有重要意义。

    总的来说,行级锁的加锁机制相当复杂,理解这些细节对于优化数据库性能和解决并发控制问题至关重要。通过实际案例的实验,我们可以更直观地看到不同类型的索引在行级锁中的表现差异,并为实际应用中的锁定策略提供参考依据。

    转载地址:http://gfbfk.baihongyu.com/

    你可能感兴趣的文章
    object detection错误之Could not create cudnn handle: CUDNN_STATUS_INTERNAL_ERROR
    查看>>
    object detection错误之no module named nets
    查看>>
    Object of type 'ndarray' is not JSON serializable
    查看>>
    Object Oriented Programming in JavaScript
    查看>>
    object references an unsaved transient instance - save the transient instance before flushing
    查看>>
    Object.assign用法
    查看>>
    Object.create
    查看>>
    Object.keys()的详解和用法
    查看>>
    objectForKey与valueForKey在NSDictionary中的差异
    查看>>
    Objective - C 小谈:消息机制的原理与使用
    查看>>
    OBJECTIVE C (XCODE) 绘图功能简介(转载)
    查看>>
    Objective-C ---JSON 解析 和 KVC
    查看>>
    Objective-C 编码规范
    查看>>
    Objective-Cfor循环实现Factorial阶乘算法 (附完整源码)
    查看>>
    Objective-C——判断对象等同性
    查看>>
    objective-c中的内存管理
    查看>>
    Objective-C之成魔之路【7-类、对象和方法】
    查看>>
    Objective-C享元模式(Flyweight)
    查看>>
    Objective-C以递归的方式实现二叉搜索树算法(附完整源码)
    查看>>
    Objective-C内存管理教程和原理剖析(三)
    查看>>