SQL数据库事务隔离通过一致性视图实现,其在首次SELECT时创建(只读显式事务除外),依据trx_ids、up_limit_id和low_limit_id判断版本可见性,并在不同隔离级别下呈现READ UNCOMMITTED不使用、RC每次新建、RR复用、SERIALIZABLE加锁等行为。

SQL数据库的事务隔离通过一致性视图(Consistent Read View)实现,核心是为每个事务在启动时创建一个“快照”,使其只能看到该时刻已提交的数据版本,从而避免脏读、不可重复读等问题。
一致性视图的生成时机
在InnoDB中,一致性视图并非在事务开始(BEGIN)时立即生成,而是在事务执行第一个SELECT语句(即首次进入一致性读)时才构建。这个视图记录了当前所有活跃事务ID的集合(trx_ids)、最小未分配事务ID(up_limit_id)和最大已提交事务ID(low_limit_id)。
- 若事务为只读且显式声明(START TRANSACTION READ ONLY),则视图在事务开启时就建立
- 若事务含写操作(如INSERT/UPDATE),即使先执行SELECT,其一致性视图仍按首次SELECT时间点确定
- 自动提交的单条SELECT语句也会创建瞬时一致性视图,执行完即丢弃
可见性判断的核心规则
当查询某行数据时,InnoDB会检查该行最近版本的DB_TRX_ID(最后修改它的事务ID),并依据以下逻辑决定是否可见:
- 若DB_TRX_ID low_limit_id:说明该版本在当前事务启动前已提交 → 可见
- 若DB_TRX_ID ≥ up_limit_id:说明该版本由当前事务之后的事务生成 → 不可见
- 若DB_TRX_ID ∈ [up_limit_id, low_limit_id):需进一步检查是否在活跃事务列表(trx_ids)中;若在,则该事务未提交 → 不可见;否则可见
不同隔离级别下的视图行为差异
一致性视图的生命周期和复用方式直接决定隔离级别效果:
- READ UNCOMMITTED:不使用一致性视图,直接读最新版本 → 可能脏读
- READ COMMITTED:每次SELECT都新建视图 → 同事务内多次读可能结果不同(不可重复读)
- REPEATABLE READ:仅第一次SELECT创建视图,后续复用 → 同事务内读一致
- SERIALIZABLE:对所有SELECT加读锁,本质上退化为串行执行,视图机制仍存在但被锁机制覆盖
影响视图有效性的常见因素
一致性视图依赖事务ID和undo log链,以下情况可能导致预期外行为:
- 长事务不提交:导致trx_ids列表膨胀,低事务ID版本无法被purge,占用大量undo空间
- 主从延迟场景下:从库回放时基于自身事务ID构造视图,与主库不完全等价
- 使用NOW()或SYSDATE()等函数时:时间值取自语句开始时刻,与视图时间点一致;但若嵌套子查询触发多次SELECT,可能涉及多个视图










