MySQL RC与RR隔离级别区别及实战锁机制详解

慢慢来
慢慢来
发布时间:2026-10-16| 4人浏览过
原创

在MySQL数据库中,RR(Repeatable Read,可重复读)是默认的隔离级别,而RC(Read Committed,读已提交)则具有更高的并发度。两者最核心的区别在于RR采用Next-Key Lock解决幻读问题,可能导致范围查询时锁住更多记录;而RC仅锁定具体行,且每条SELECT语句产生独立的一致性快照。

核心差异:加锁机制与并发性能

理解锁的机制是选择隔离级别的关键:

  • RR隔离级别:支持 GAP Lock(间隙锁)。为了彻底解决幻读问题,它会对符合条件的数据进行行锁并扩展至区间间隙。
  • RC隔离级别:不使用GAP Lock。它通过非索引列过滤后,会释放不满足条件的行锁。虽然这违反了严格的“两阶段加锁原则”,但显著减少了锁竞争,降低了死锁和锁超时的概率,并发性能优于RR。
  • BINLOG兼容性:RC隔离级别不支持 STATEMENT 格式的binlog(易导致主从数据不一致),必须使用 MIXED 或 ROW 格式。这也是MySQL默认设为RR的重要原因之一。
  • 一致性读快照(ReadView):RC下每一条SELECT都拥有自己的ReadView(读取执行时已提交的最新数据);RR下整个事务共享同一个ReadView(以第一条SELECT为准)。

第一步骤:创建测试数据

首先构建一个基础测试表,包含普通字段和非唯一索引,用于观察不同条件下的锁行为。

create table a (
id int auto_increment,
a varchar(10),
b varchar(10),
c varchar(10),
d varchar(10),
 primary key(id) 
) engine=INNODB default charset=utf8;

insert into a(a,b,c,d) values 
('1','1','1','1'),('2','2','2','2'),('3','3','3','3'),
('4','4','4','4'),('5','5','5','5'),('6','6','6','6');

CREATE INDEX index_b_c ON a(b,c); 

RR隔离级别下的锁表现

查看当前系统隔离级别:

show variables like '%iso%';
-- Variable_name: transaction_isolation | Value: REPEATABLE-READ

第二步骤:无索引条件下的锁表现

当 WHERE 条件走全表扫描(无索引)时,RR级别会表现出类似锁全表的行为:

  1. 事务1启动并更新ID为1的行:
    begin; update a set d='20' where a='1'; commit;
  2. 事务2尝试更新ID为2的行:
    begin; update a set d='20' where a='2'; 
    此时事务2会因为获取不到锁而阻塞,最终因超过等待时间报错 ERROR 1205 (HY005): Lock wait timeout exceeded。

原因分析:在RR模式下,由于没有走索引,InnoDB无法精确定位到单条记录,进而对该范围内的所有索引/数据行施加了间隙锁(GAP Lock),导致其他事务即使更新不同的行也会发生冲突。

第三步骤:有索引条件下的锁表现

若利用索引 index_b_c 进行查询,锁粒度会缩小:

  1. 事务1:更新 b='2'(命中索引行id=2)。
  2. 事务2:更新 b='3'(命中索引行id=3)。

此时两个操作可以同时运行。这是因为它们各自仅锁定了特定的索引行及相应的间隙,互不干扰。通过 performance_schema.data_locks 可观察到具体的Lock Mode。

验证结论:在使用RR隔离级别时,如果更新条件未命中索引,极大概率会导致大范围甚至全表级别的锁等待。

RC隔离级别下的锁表现

修改全局设置开启RC模式:

set global transaction_isolation='read-committed';

第四步骤:非索引更新测试

在无索引字段上进行多事务并发操作:

  1. 事务1:修改 a='1' 的记录。
  2. 事务2:修改 a='2' 的记录。由于RC不包含Gap Lock,此处不会发生长时间锁等待,事务可以顺利执行并提交。

在事务2中执行 SELECT,可以看到事务1已提交(commit)的数据变更。这证明了RR隔离级别的“不可重复读”现象——即在同一事务中多次读取同一条记录,结果可能因为其他事务的提交而发生变化。

第五步骤:锁结构验证

通过查询视图确认此时的锁状态:

-- 数据锁情况
select * from performance_schema.data_locks;
-- LOCK_MODE: X,REC_NOT_GAP (只有行锁,没有间隙锁)

-- 事务等待情况
select * from data_lock_waits;
-- Empty set (无阻塞)

总结

RC与RR的主要区别决定了应用场景的选择:

  1. 并发优先选RC:RC下不持有间隙锁,非命中索引的行在执行完操作后会迅速释放锁资源,极大降低了死锁风险和等待时间。
  2. 强一致性选RR:RR保证了事务内多次读取的一致性,消除了幻读,适合对数据一致性要求极高但不介意一定程度性能损耗的场景。
  3. 运维注意:若强制将默认隔离级别改为RC,需确保Binlog格式设置为 row 或 mixed。

以上就是MySQL中隔离级别RC与RR的区别及锁机制的详细解读,更多关于MySQL高性能配置的资料请关注本站其它相关文章!

相关标签:

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。