一致性读的快照在首次SELECT时基于Read View动态构建,非事务启动时物理拷贝;InnoDB的Read View含m_ids、min_trx_id、max_trx_id和creator_trx_id,结合记录DB_TRX_ID判断可见性。

SQL数据库中的一致性读(Consistent Read)依赖于快照(Snapshot)机制,而快照的生成时机直接决定事务能看到哪些数据版本。关键在于:快照并非在事务开始时立即完整拷贝数据,而是在**第一次执行SELECT等一致性读语句时,基于当前全局事务视图(Read View)动态构建逻辑快照**。
快照不是物理拷贝,而是逻辑视图
多数支持MVCC的数据库(如MySQL InnoDB、PostgreSQL)并不在事务启动时复制整库数据。而是维护一个活跃事务ID列表和版本链信息。当事务首次执行SELECT时,系统根据此时的事务状态生成Read View,确定哪些事务的修改对本事务可见。
- InnoDB中,Read View包含:m_ids(生成时刻所有活跃未提交事务ID列表)、min_trx_id(最小活跃ID)、max_trx_id(下一个将分配的ID)、creator_trx_id(当前事务自身ID)
- 每行记录的DB_TRX_ID字段用于比对:只有满足可见性规则(如trx_id
快照生成发生在“第一次一致性读”时刻
事务开启(BEGIN/START TRANSACTION)本身不触发快照创建。真正决定数据可见范围的时间点是该事务内**第一条非锁定读(即普通SELECT)被执行的瞬间**。
- 若事务先执行UPDATE/INSERT再SELECT,快照仍以SELECT执行时的系统状态为准
- 若事务全程只做DML无SELECT,则可能根本不生成Read View(不涉及一致性读)
- 显式加锁的SELECT(如SELECT ... FOR UPDATE)不走一致性读,不依赖该快照
不同隔离级别影响快照生命周期
快照一旦生成,在事务内持续有效,但其“有效性边界”受隔离级别约束:
- READ COMMITTED:每次执行SELECT都新建Read View,快照随语句刷新
- REPEATABLE READ(InnoDB默认):仅第一次SELECT生成Read View,后续SELECT复用同一快照,保障可重复读
- READ UNCOMMITTED:不使用快照,直接读最新行版本(可能脏读)
- SERIALIZABLE:自动为SELECT加共享锁,退化为锁读,快照机制基本不生效
写操作不影响当前事务的快照内容
事务A在生成快照后执行UPDATE,只会新写入带新trx_id的行版本,并标记旧版本过期;事务B的已有快照仍按原规则判断可见性,不会因A的修改而自动更新自身快照。
- 这意味着:同一事务内多次SELECT看到的数据是一致的,即使其他事务并发修改了这些行
- 但注意:若事务A自己修改了某行并再次SELECT,InnoDB会优先读取自己的最新修改(当前读),而非快照中的旧版本










