MySQL innodb行锁加锁规则

本文深入探讨了MySQL InnoDB存储引擎的行锁机制,详细解析了在不同查询条件下(主键索引、唯一索引、普通索引和非索引)的加锁规则。在等值查询和范围查询中,根据记录是否存在,讨论了记录锁、间隙锁和邻键锁的使用情况,展示了如何在RR隔离级别下防止并发写冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

利用隐藏字段roll_pointer、版本链、ReadView来实现的MVCC,可以很好地解决多个事务的并发【读+写】问题,但是如果在多个事务并发【写+写】的情况下,则需要用到锁了。
MySQL提供了很多种锁:

Server层实现了全局锁和元数据锁。

数据引擎中,MyISAM、Memory等存储引擎实现了表锁(且只支持表锁),BerkeleyDB存储引擎实现了页级锁,InnoDB实现了行锁和表锁。

平时最常用的就是InnoDB的行锁,所以在这里主要来探索一下InnoDB的行锁。

顾名思义,行锁就是给数据库表中每行数据加锁,行锁是加在索引上的,比如某个表中id字段是主键,如果给id=2这条记录加锁,那这把锁是加在主键索引(聚簇索引)上的。如果为某个没有索引的字段加锁,最终会在主键索引上锁住所有的记录。在InnoDB的实现中,行锁有3种主要的实现:

  1. Record Lock:对单个行记录上锁,这里我们称为记录锁。
  2. Gap Lock:对不包含真实存在记录的某一个间隙/范围加锁,这里我们称它为间隙锁,间隙锁只有一个目的就是在RR、SERIALIZABLE隔离级别下为了防止其他事务插入数据。假如一个索引有2、4、5、9、12 五个值,那该索引可能被间隙锁锁的范围为(-∞ , 2),(2 , 4),(4 , 5),(5 , 9),(9 , 12),(12 , +∞)。
  3. Next-Key Lock:相当于Record Lock+Gap Lock,对【某一个行记录】和【这条记录与它前一条记录之间的范围/间隙】都上锁,这里我们称它为邻键锁。假如一个索引有2、4、5、9、12 五个值,那该索引可能被邻键锁锁的范围为(-∞ , 2],(2 , 4],(4 , 5],(5 , 9],(9 , 12],(12 , +∞)。

在InnoDB中,加锁的基本单位是Next-Key Lock,只不过在某些特殊情况下会退化为 Record Lock 或者 Gap Lock。
在实际场景中,行级锁加锁规则比较复杂,不同的查询条件,不同的索引,不同的隔离级别,加锁的情况可能不同,甚至不同版本的MySQL加锁规则也可能会稍有差异。

这里我们围绕下面这个问题,记录一下MySQL在默认的RR隔离级别下的行锁加锁情况(RC隔离级别下只会对记录加Record Lock,不会加Gap Lock 和 Next-Key Lock)。

  1. 查询条件是等值查询或范围查询,查询结果存在或不存在,对应索引是主键索引或唯一索引或普通索引时,会怎么加锁?

创建和初始化表:

CREATE TABLE `t_lock_test` (
  `id` int NOT NULL,
  `mobile` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `age` int DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_mobile` (`mobile`) USING BTREE,
  KEY `idx_name` (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

INSERT INTO `t_lock_test
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_33080131

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值