快照读与当前读
总结
介绍对比快照读与当前读,以及 事务隔离级别 对快照读的影响。
简介
在 MySQL(尤其是使用 InnoDB 存储引擎)中,快照读(Snapshot Read)和当前读(Current Read)是两种不同的读取方式,它们在事务隔离级别下对数据可见性有不同的处理方式,特别是在使用多版本并发控制(MVCC)时表现明显。
详情
快照读(Snapshot Read)
定义:
快照读是指在事务中读取一个 一致性读视图(Consistent Read View)下的数据快照,而不是当前数据库中的最新数据。这种读取方式通常用于普通的 SELECT
语句。
示例:
SELECT * FROM users WHERE id = 1;
特点:
- 使用的是 MVCC(多版本并发控制) 机制,读取的是数据的历史版本。
- 不加锁(除非显式加锁),不会阻塞其他事务的写操作。
- 在可重复读(REPEATABLE READ)隔离级别下,一个事务在整个生命周期中看到的是事务开始时的数据快照。
- 在读已提交(READ COMMITTED)隔离级别下,每次查询会生成一个新的一致性视图。
适用场景:
适用于不需要获取最新数据的场景,例如报表查询、数据分析等。
当前读(Current Read)
定义:
当前读是指读取数据的最新版本,并通常会对读取的数据加锁,以防止其他事务修改。这种读取方式会触发锁机制,确保读到的是最新的数据,并防止并发写入。
示例:
以下 SQL 语句都会触发当前读:
SELECT * FROM users WHERE id = 1 FOR UPDATE;
SELECT * FROM users WHERE id = 1 LOCK IN SHARE MODE;
UPDATE users SET name = 'Tom' WHERE id = 1;
DELETE FROM users WHERE id = 1;
INSERT INTO users (name) VALUES ('Jerry');
特点:
- 读取的是最新的数据版本。
- 会加锁(排他锁或共享锁),可能阻塞其他事务的读写。
- 不依赖 MVCC 的一致性视图,而是直接读取当前最新数据。
- 保证读取的数据在事务提交前不会被其他事务修改。
适用场景:
适用于需要保证数据最新性、并且可能需要进行修改的场景,例如事务中的写操作、转账、库存扣减等。
表格对比
类型 | 是否加锁 | 读取版本 | 是否触发 MVCC | 是否阻塞其他事务 | 隔离级别影响 | 典型语句 | 场景 |
---|---|---|---|---|---|---|---|
快照读 | 否 | 历史版本 (一致性读视图) | 是 | 否 | 明显(尤其在 RR 级别) | SELECT |
查询、报表、分析 |
当前读 | 是(排他锁或共享锁) | 最新版本 | 否 | 是 | 不明显(总是读最新) | UPDATE , DELETE , INSERT |
修改、写操作、并发控制 |
事务隔离级别对快照读的影响
- READ UNCOMMITTED:不使用快照读,直接读未提交的数据。
- READ COMMITTED(RC):每次快照读生成新的一致性视图。
- REPEATABLE READ(RR):整个事务期间使用同一个一致性视图。
- SERIALIZABLE:所有读操作都变成当前读(隐式加锁)。
举例说明
假设有一个表 users(id, name)
,初始数据为 (1, 'Alice')
。
时间点 | 事务 A | 事务 B |
---|---|---|
T0 | START TRANSACTION; |
|
T1 | SELECT * FROM users WHERE id = 1; |
|
T2 | START TRANSACTION; |
|
T3 | UPDATE users SET name = 'Bob' WHERE id = 1; |
|
T4 | COMMIT; |
|
T5 | SELECT * FROM users WHERE id = 1; |
|
T6 | SELECT * FROM users WHERE id = 1 FOR UPDATE; |
|
T7 | COMMIT; |
隔离级别 | T1 | T3 | T5(快照读) | T6(当前读) | 说明 |
---|---|---|---|---|---|
RU | Alice |
可能读到 Bob (脏读) |
Bob |
Bob |
快照读不生效,直接读最新数据,即使事务 B 尚未提交也能读到修改 |
RC | Alice |
Alice |
Bob (生成新一致性视图) |
Bob |
每次快照读生成新的一致性视图,事务 B 提交后能读到新数据 |
RR | Alice |
Alice |
Alice (保持初始一致性视图) |
Bob |
快照读在整个事务中保持一致性视图;当前读读最新数据 |
SERIALIZABLE | Alice (隐式加 S 锁) |
Alice |
Alice |
Alice |
所有普通 SELECT 都加锁,事务 B 的 UPDATE 被阻塞直到事务 A 提交 |