可重复读能“反复读同一数据却不变”是因为事务中首次SELECT时创建read view,后续查询均基于该快照;MySQL通过间隙锁+MVCC组合避免幻读,但非纯MVCC实现;RC每次SELECT新建read view,RR只建一次。

可重复读为什么能“反复读同一数据却不变”
因为 InnoDB 在事务启动时生成了一个一致性读视图(read view),它不是拷贝数据,而是通过 DB_TRX_ID 和 undo log 动态“算出”你该看到哪个版本的数据。只要事务没提交,后续所有 SELECT 都基于这个快照,哪怕其他事务已更新并提交了那行。
- 关键点:read view 是在**第一条 SELECT 执行时才创建**,不是
BEGIN时;如果你BEGIN后先UPDATE再SELECT,read view 会延迟到SELECT时刻生成 - 容易踩的坑:
autocommit=1下,单条SELECT自成事务,每次查都新建 read view,根本谈不上“可重复读” - 性能影响:高并发下活跃事务多,read view 数组变大,版本可见性判断开销略增,但远小于加锁等待
幻读真的被 MySQL 解决了吗
标准 SQL 定义中,可重复读(RR)不解决幻读;但 MySQL 的 RR 默认**用间隙锁(gap lock)+ MVCC 组合封住了 insert 场景**,所以你在普通 SELECT 中看不到新插入的行——但这不是纯靠 MVCC,是锁在起作用。
- 真实场景:事务 A 执行
SELECT * FROM t WHERE id > 5,InnoDB 不仅给查到的行加记录锁,还会对 (5, +∞) 加间隙锁;事务 B 此时INSERT INTO t VALUES (6, 'x')就会被阻塞 - 但如果你用
SELECT ... LOCK IN SHARE MODE或FOR UPDATE,间隙锁行为更明显;而纯SELECT下,间隙锁只在唯一索引/主键范围扫描时隐式启用 - 注意陷阱:RR 级别下,
INSERT ... SELECT或UPDATE ... JOIN这类语句仍可能触发幻读,因为它们走的是当前读(current read),绕过了 MVCC 快照
读已提交和可重复读的核心区别在哪一行代码里
就在 read view 的生成时机——READ COMMITTED 每次 SELECT 都新建 read view;REPEATABLE READ 整个事务只建一次。这导致前者能看到其他事务“刚提交”的变更,后者完全看不见。
面向 CRM 系统的 MySQL 8 数据库模式设计。当用户需要为客户关系管理(CRM)系统设计、评审、优化或生成数据库模式时,应使用此项技能。
- 实操验证:两个会话同时连进 MySQL,都设为
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;会话 AUPDATE并COMMIT后,会话 B 立即SELECT就能看见新值;换成REPEATABLE READ,B 必须重新开启事务才能看到 - 参数差异:
innodb_locks_unsafe_for_binlog=ON(已废弃)曾让 RR 退化为 RC 行为,现在不用管;但binlog_format=STATEMENT下,某些 RR 语义可能被复制打乱,建议用ROW - 兼容性提醒:PostgreSQL 的 RR 是真正快照隔离(SI),不会出现 MySQL 的间隙锁阻塞;迁移时要注意 insert 并发逻辑是否依赖这种“阻塞”
什么时候必须用锁,而不是靠 MVCC
MVCC 只管“读不阻塞”,但凡你要确保“读之后立刻写不冲突”,就得显式加锁——比如秒杀扣库存、银行转账余额校验,这类场景 MVCC 的快照无法防止写覆盖。
- 典型错误:用
SELECT balance FROM account WHERE id = 1得到 100,再UPDATE account SET balance = 90 WHERE id = 1 AND balance = 100,看似乐观锁,但如果并发高且没加FOR UPDATE,两次 SELECT 可能都读到 100,第二个 UPDATE 仍会成功,造成超扣 - 正确做法:把
SELECT改成SELECT balance FROM account WHERE id = 1 FOR UPDATE,这样第二个人来查就会等,或者直接失败(取决于 innodb_lock_wait_timeout) - 性能权衡:
FOR UPDATE是排他锁,会锁住索引记录+间隙,比纯 MVCC 查慢,但换来的是数据强一致;线上核心链路该锁还得锁,别迷信“无锁就快”
MVCC 和锁从来不是二选一,而是分工明确:MVCC 解决读-写冲突,锁解决写-写和读-写强一致需求。很多人卡在“为什么我开了 RR 还要加锁”,答案就在这里——快照只保你看得一致,不保你改得安全。

















