博客
关于我
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/

    你可能感兴趣的文章
    Numpy:按多个条件过滤行?
    查看>>
    Numpy:条件总和
    查看>>
    numpy、cv2等操作图片基本操作
    查看>>
    numpy中的argsort的用法
    查看>>
    NumPy中的精度:比较数字时的问题
    查看>>
    numpy判断对应位置是否相等,all、any的使用
    查看>>
    Numpy多项式.Polynomial.fit()给出的系数与多项式.Polyfit()不同
    查看>>
    Numpy如何使用np.umprod重写range函数中i的python
    查看>>
    numpy学习笔记3-array切片
    查看>>
    numpy数组替换其中的值(如1替换为255)
    查看>>
    numpy数组索引-ChatGPT4o作答
    查看>>
    numpy最大值和最大值索引
    查看>>
    NUMPY矢量化np.prod不能构造具有超过32个操作数的ufunc
    查看>>
    Numpy矩阵与通用函数
    查看>>
    numpy绘制热力图
    查看>>
    numpy转PIL 报错TypeError: Cannot handle this data type
    查看>>
    Numpy闯关100题,我闯了95关,你呢?
    查看>>
    nump模块
    查看>>
    Nutch + solr 这个配合不错哦
    查看>>
    NuttX 构建系统
    查看>>