MySQL的可重复读事务隔离级别的实现原理

发布于:2025-05-22 ⋅ 阅读:(12) ⋅ 点赞:(0)

在MySQL中,可重复读事务隔离级别主要是通过MVCC(多版本并发控制)和锁机制来实现的。
 
MVCC机制
 
- 生成Read View:事务开始时,会生成一个Read View,它记录了当前系统中活跃事务的ID列表、最小活跃事务ID和最大事务ID。
- 数据版本判断:在读取数据时,根据数据行的 DB_TRX_ID 与Read View进行比较,若 DB_TRX_ID 小于最小活跃事务ID,数据对当前事务可见;若大于最大事务ID,不可见;若在活跃事务ID范围内,且不在活跃事务列表中,则可见。以此确保事务在整个生命周期内看到的数据版本是一致的。
 
锁机制
 
- 行锁:对于并发的写操作,MySQL会使用行锁来确保同一时刻只有一个事务能修改某一行数据,避免数据冲突。
- Next - Key Lock:在InnoDB存储引擎中,还使用Next - Key Lock来防止幻读。它会锁定一个范围,包括索引记录本身和相邻的间隙,阻止其他事务在该范围内插入新记录。
 
通过MVCC和锁机制的结合,MySQL的可重复读隔离级别既能保证事务内数据的一致性,又能在一定程度上提高并发性能,减少锁的竞争和等待。

Next - Key Lock

Next key lock是行锁和间隙锁的组合。
 
Next - Key Lock会锁定一个范围,既包括索引记录本身(行锁的功能),又包括索引记录之间的间隙(间隙锁的功能)。例如,对于索引值为10、20、30的记录,Next - Key Lock会锁定(10, 20)、(20, 30)等间隙以及10、20、30这些索引记录本身,这样可以有效防止幻读和数据冲突,在并发场景下更好地保证数据的一致性。

Next - Key Lock的加锁规则

Next - Key Lock的加锁规则较为复杂,以下是一些常见的规则:
 
等值查询
 
- 唯一索引:对于唯一索引的等值查询,若查询记录存在,仅对该记录加行锁;若记录不存在,会在该唯一值的前后间隙加Next - Key Lock。例如,表中有唯一索引列 id ,执行 SELECT * FROM table WHERE id = 5 ,若存在 id 为5的记录,只对该记录加锁;若不存在,则会在小于5和大于5的间隙加锁。
- 普通索引:在普通索引上进行等值查询时,会对查询到的记录及其所在的间隙加Next - Key Lock。如果查询的记录不存在,会对该索引值两侧的间隙加锁。例如,有普通索引列 age ,执行 SELECT * FROM table WHERE age = 30 ,若有 age 为30的记录,会对这些记录及相邻间隙加锁;若没有,会对小于30和大于30的间隙加锁。
 
范围查询
 
- 全值匹配:当使用唯一索引进行全值匹配的范围查询时,会对范围内的记录加行锁,对范围外的间隙加间隙锁。例如, SELECT * FROM table WHERE id BETWEEN 10 AND 20 ,如果 id 是唯一索引,会对 id 为10到20的记录加行锁,对小于10和大于20的间隙加间隙锁。
- 非唯一索引或无索引:对于普通索引或无索引列的范围查询,会对范围内的所有记录以及这些记录之间的间隙加Next - Key Lock。例如, SELECT * FROM table WHERE age BETWEEN 30 AND 40 ,如果 age 是普通索引或无索引,会对满足条件的所有记录及它们之间的间隙加锁。
 
插入操作
 
- 插入操作会对插入位置的前一个间隙加Next - Key Lock,以防止其他事务在该位置插入数据,避免出现幻读。例如,在一个有序的索引列中,要插入一个值为5的记录,会对小于5的最大索引值和5之间的间隙加锁。
 
需要注意的是,这些规则是基于InnoDB存储引擎在可重复读隔离级别下的默认行为,实际应用中可能会因版本、配置等因素有所不同。


网站公告

今日签到

点亮在社区的每一天
去签到