博客
关于我
MySQL 的全局锁、表锁和行锁
阅读量:810 次
发布时间: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/

    你可能感兴趣的文章
    Plotly:如何使用 plotly.graph_objects 和 plotly.express 定义图形中的颜色?
    查看>>
    Plotly:如何使用 Python 对绘图对象条形图进行颜色编码?
    查看>>
    Plotly:如何使用 updatemenus 更新一个特定的跟踪?
    查看>>
    Plotly:如何使用长格式或宽格式的 pandas 数据框制作线图?
    查看>>
    Plotly:如何向烛台图添加交易量
    查看>>
    Plotly:如何在 plotly express 中找到趋势线的系数?
    查看>>
    Plotly:如何在桑基图中设置节点位置?
    查看>>
    Plotly:如何处理重叠的颜色条和图例?
    查看>>
    Plotly:如何手动设置 plotly express 散点图中点的颜色?
    查看>>
    Plotly:如何结合 make_subplots() 和 ff.create_distplot()?
    查看>>
    Plotly:如何绘制累积的“步骤“;直方图?
    查看>>
    Quartz进一步学习与使用
    查看>>
    Plotly条形图-根据正/负值更改颜色-python
    查看>>
    PLSQL developer12安装图解
    查看>>
    PLSQL Developer调试 存储过程和触发器
    查看>>
    PLSQL window操作
    查看>>
    plsql 存储过程 测试
    查看>>
    plsql 安装后database下拉没有东西
    查看>>
    PLSQL_Oracle PLSQL内置函数大全(概念)
    查看>>
    PLSQL_案例优化系列_体验逻辑结构如何影响SQL优化(案例3)
    查看>>