MySQL 之锁机制

news/2024/10/20 20:54:25/

在 MySQL 数据库中,锁机制是保证数据一致性和并发控制的重要手段。不同类型的锁在不同的场景下发挥着关键作用,下面将详细解释 MySQL 中的行锁、GAP 锁(间隙锁)、临键锁的作用和实现原理。

一、行锁

  1. 作用

    • 行锁是对数据库表中的一行数据进行加锁,用于确保在并发事务中对同一行数据的操作是互斥的。行锁可以最大程度地提高并发性能,因为它只锁定了需要操作的数据行,而不会影响其他行的数据。
    • 例如,在一个银行系统中,当一个用户进行转账操作时,需要对转出账户和转入账户的余额进行更新。如果没有行锁,可能会出现两个并发的转账事务同时对同一账户的余额进行更新,导致数据不一致。使用行锁可以确保在一个事务对某一账户余额进行更新时,其他事务不能同时对该账户进行操作,从而保证数据的一致性。
  2. 实现原理

    • MySQL 中的行锁是通过在存储引擎层实现的。不同的存储引擎对行锁的实现方式可能会有所不同。以 InnoDB 存储引擎为例,它使用了一种称为 “意向锁” 的机制来辅助行锁的实现。
    • 意向锁是一种表级锁,它表示事务在某一范围内(如表、页或行)有意向加锁。当事务需要对一行数据加行锁时,首先会在表级别加上意向锁,然后再对该行数据加上行锁。这样可以让数据库系统快速判断是否有其他事务在表级别或更高层次上加了锁,从而避免不必要的锁冲突检测。
    • 当一个事务对一行数据加行锁时,其他事务如果也需要对同一行数据进行操作,就必须等待该事务释放行锁。只有当行锁被释放后,其他事务才能获取该行数据的锁并进行操作。

二、GAP 锁(间隙锁)

  1. 作用

    • GAP 锁主要用于防止幻读现象的发生。幻读是指在一个事务中,两次查询同一范围的数据,第二次查询结果中出现了第一次查询中没有的数据行,这通常是由于其他事务在两次查询之间插入了新的数据行导致的。
    • GAP 锁通过锁定数据行之间的间隙,防止其他事务在这个间隙中插入新的数据行,从而避免幻读的发生。例如,在一个订单管理系统中,一个事务需要查询订单编号在 100 到 200 之间的订单。如果没有 GAP 锁,另一个事务可能在这个范围内插入一个新的订单,导致第一个事务在第二次查询时出现幻读。使用 GAP 锁可以锁定这个范围内的间隙,防止其他事务插入新的订单,从而避免幻读。
  2. 实现原理

    • InnoDB 存储引擎在可重复读隔离级别下会自动使用 GAP 锁。当一个事务对一个范围的数据进行查询时,InnoDB 会在这个范围内的数据行上加上共享锁,同时在数据行之间的间隙上加上 GAP 锁。
    • GAP 锁是一种区间锁,它锁定的是一个数据行之间的间隙,而不是具体的数据行。例如,如果一个事务对订单编号在 100 到 200 之间的订单进行查询,InnoDB 会在订单编号为 100 的数据行上加上共享锁,在订单编号为 200 的数据行上也加上共享锁,同时在 100 和 200 之间的间隙上加上 GAP 锁。
    • 当其他事务试图在这个间隙中插入新的数据行时,会被 GAP 锁阻塞,直到持有 GAP 锁的事务提交或回滚,释放了 GAP 锁,其他事务才能插入新的数据行。

三、临键锁(Next-Key Lock)

  1. 作用

    • 临键锁是一种组合锁,它由行锁和 GAP 锁组成。临键锁既可以防止其他事务对同一行数据进行修改,又可以防止其他事务在该行数据的前后间隙中插入新的数据行,从而有效地避免了幻读现象的发生。
    • 例如,在一个库存管理系统中,一个事务需要查询库存数量在 100 到 200 之间的商品。如果使用临键锁,InnoDB 会在这个范围内的每个商品数据行上加上行锁,同时在数据行之间的间隙上加上 GAP 锁。这样可以确保在这个事务执行期间,其他事务既不能修改这个范围内的商品数据行,也不能在这个范围内插入新的商品数据行,从而避免了幻读。
  2. 实现原理

    • 临键锁是 InnoDB 存储引擎在可重复读隔离级别下默认使用的锁机制。当一个事务对一个范围的数据进行查询或更新时,InnoDB 会自动为这个范围内的每个数据行加上行锁,同时在数据行之间的间隙上加上 GAP 锁,从而形成临键锁。
    • 临键锁的实现是通过在索引树上进行加锁来实现的。InnoDB 存储引擎使用 B + 树作为索引结构,当一个事务对一个范围的数据进行查询或更新时,InnoDB 会在索引树上找到这个范围的数据行,并在这些数据行对应的节点上加上行锁和 GAP 锁。
    • 当其他事务试图对这个范围内的数据行进行修改或在这个范围内插入新的数据行时,会被临键锁阻塞,直到持有临键锁的事务提交或回滚,释放了临键锁,其他事务才能进行操作。

总之,MySQL 中的锁机制是一个复杂而重要的主题。行锁、GAP 锁和临键锁在不同的场景下发挥着不同的作用,它们共同保证了 MySQL 数据库在并发环境下的数据一致性和事务隔离性。理解这些锁的作用和实现原理,对于优化数据库性能、避免死锁和提高系统的可靠性都具有重要意义。


http://www.ppmy.cn/news/1538697.html

相关文章

大数据-160 Apache Kylin 构建Cube 按照日期构建Cube 详细记录

点一下关注吧!!!非常感谢!!持续更新!!! 目前已经更新到了: Hadoop(已更完)HDFS(已更完)MapReduce(已更完&am…

Starrocks的表引擎选择及表属性的设置详细说明

表引擎选择 OLAP引擎 特点与适用场景: 这是StarRocks中用于数据分析场景的主要引擎。它针对海量数据的复杂分析查询进行了优化,能够高效地处理聚合、分组、排序等操作。例如,在数据仓库场景下,当需要对销售数据进行按地区、时间等…

iOS NSString 使用Copy修饰,而不使用Strong修饰

其实老实讲, 定义property 属性,“使用Copy修饰,而不是用Strong修饰”这句话也不完全正确.因为如果他们对接的是不可变字符串,那么无论使用哪个都一样. 问题就出现在,如果他们对接的是可变字符串NSMutableString,那就得用copy 定义两个NSString 属性: interface ViewControl…

利用编程思维做题之将两个有序的单链表合并成一个新的有序单链表

1. 理解问题 将两个有序的单链表合并成一个新的单链表,并且保持有序。每个链表的元素按照升序排列,合并后的链表也需要保持升序。 示例: 假设我们有两个有序链表: 链表 1:1 -> 3 -> 5链表 2:2 -&g…

python爬虫 - 深入requests模块

🌈个人主页:https://blog.csdn.net/2401_86688088?typeblog 🔥 系列专栏:https://blog.csdn.net/2401_86688088/category_12797772.html 目录 前言 一、下载网络文件 (一)基本步骤 (二&…

【C++几种单例模式解读及实现方式】

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、单例是什么?二、解读1.懒汉式2.饿汉式3.static变量特性4.call_once特性 总结 前言 单例模式几乎是每种语言都不可少的一种设计模式&#xff0c…

Redis 典型应用之缓存

目录 1. 缓存的基本概念 2. 使用 Redis 作为缓存 3. 缓存的更新策略 3.1 定期生成 3.2 实时生成 3.2.1 内存淘汰策略 1. FIFO (First In First Out) 先进先出 2. LRU (Least Recently Used) 淘汰最久未使使用的 3. LFU (Least Frequently Used) 淘汰访问次数最少的 4…

【uni-app】HBuilderX安装uni-ui组件

目录 1、官网找到入口 2、登录帐号 3、打开HuilderX 4、选择要应用的项目 5、查看是否安装完成 6、按需安装 7、安装完毕要重启 8、应用 前言:uniapp项目使用uni-ui组件方式很多,有npm安装等,或直接创建uni-ui项目,使用un…