mysql的快照读与当前读的区别
这两个是 MySQL InnoDB 在 MVCC 下的两种主要读方式,区别核心在于 是否加锁、是否读到最新数据。
1. 快照读(Snapshot Read)
定义:
通过 MVCC(多版本并发控制) 机制读取某行数据的历史版本(基于事务启动时的快照),不加锁。
特点:
- 读的是事务开始时能看到的数据版本(符合隔离级别规则)。
- 不会阻塞其他事务的更新,也不会被更新阻塞。
- 实现原理依赖 InnoDB 的
undo log
,在需要时从旧版本回溯数据。 - 常用于 一致性非锁定读(Consistent Non-locking Read)。
典型 SQL:
SELECT * FROM table WHERE id = 1;
只要不是 SELECT ... LOCK
或加 FOR UPDATE
,就是快照读。
适用场景:
- 大部分普通查询
- 减少锁竞争
- 保证一致性读取
2. 当前读(Current Read)
定义:
直接读取 记录的最新版本,并且加锁,保证其他事务不能修改它直到当前事务结束(或释放锁)。
特点:
- 读取的是此刻最新的数据版本。
- 会加共享锁(S)或排他锁(X),阻塞其他可能冲突的事务。
- 常用于需要“读后立刻更新”的场景。
典型 SQL:
SELECT * FROM table WHERE id = 1 FOR UPDATE; -- 加排他锁
SELECT * FROM table WHERE id = 1 LOCK IN SHARE MODE; -- 加共享锁
UPDATE table SET value = value + 1 WHERE id = 1; -- 更新也是当前读
DELETE FROM table WHERE id = 1; -- 删除也是当前读
适用场景:
- 需要马上更新读取到的数据
- 防止幻读、并发修改
3. 对比总结
维度 | 快照读 | 当前读 |
---|---|---|
读取版本 | 事务开始时可见版本(历史版本) | 最新版本 |
是否加锁 | ❌ 否 | ✅ 是 |
是否阻塞 | ❌ 不阻塞 | ✅ 可能阻塞或被阻塞 |
实现依赖 | MVCC + Undo Log | 锁(Record Lock, Gap Lock, Next-Key Lock) |
场景 | 普通查询 | 更新前读取、并发控制 |
📌 记忆技巧:
- “快照读” → 拍张照片,读照片里的数据,照片不会变(历史一致性)。
- “当前读” → 直接看现实中的人,并且拉住他不让走(加锁防别人动数据)。
如果你愿意,我可以帮你画一张 事务时间线对比图,把快照读和当前读的可见性差异直观画出来,方便记忆。这样你在面试讲解时更容易说清楚。
你需要我画这张图吗?