2026-10-20 15:19:51
MySQL事务通过MVCC(多版本并发控制)和锁机制共同实现高并发下的数据一致性,MVCC解决读不加锁问题,锁机制解决写冲突问题,二者配合在不同隔离级别下提供不同的并发控制能力。具体实现原理如下:
MVCC实现原理MVCC通过维护数据的多个版本实现读写不冲突,核心机制包括undo log版本链和ReadView快照机制。
undo log版本链InnoDB每行数据包含隐藏列:事务ID(trx_id)和指向undo log的指针(roll_pointer)。每次数据修改会生成一条undo log,记录修改前的数据状态,并通过roll_pointer指向前一条undo log,形成版本链。例如:

ReadView快照机制ReadView是事务在某一时刻对系统活跃事务的“快照”,包含四个关键属性:
m_ids:生成ReadView时系统中活跃的读写事务ID列表。
min_trx_id:m_ids中的最小事务ID。
max_trx_id:系统分配给下一个事务的ID(预分配值)。
creator_trx_id:生成当前ReadView的事务ID。
版本可见性判断规则:
若被访问版本的trx_id等于creator_trx_id,当前事务访问自己修改的记录,版本可见。
若trx_id < min_trx_id,生成该版本的事务已提交,版本可见。
若min_trx_id ≤ trx_id < max_trx_id:
若trx_id在m_ids中,生成该版本的事务未提交,版本不可见。
若trx_id不在m_ids中,生成该版本的事务已提交,版本可见。
若trx_id ≥ max_trx_id,生成该版本的事务在当前事务之后启动,版本不可见。
若版本不可见,沿版本链查找下一个版本,直到找到可见版本或遍历完所有版本(此时记录对当前事务完全不可见)。
不同隔离级别通过MVCC和锁的组合实现不同的并发控制效果:
READ UNCOMMITTED(读未提交)
直接读取记录的最新版本,不生成ReadView。
可能读取到未提交的数据(脏读),无锁机制。
READ COMMITTED(读已提交,RC)
快照读:每次读取数据前生成新的ReadView,保证每次读取看到已提交的最新数据。
当前读:通过加锁(记录锁)读取最新版本,避免脏读,但存在不可重复读和幻读。
示例:事务A第一次读取数据生成ReadView1,事务B提交修改后,事务A再次读取生成ReadView2,可能看到事务B的修改。
REPEATABLE READ(可重复读,RR)
快照读:在第一次读取数据时生成ReadView,后续读取复用该ReadView,保证同一事务内多次读取结果一致。
当前读:通过加锁(记录锁+间隙锁)防止其他事务修改或插入数据,避免不可重复读和幻读。
间隙锁(Gap Lock):锁住索引记录之间的间隙,防止其他事务插入满足查询条件的新记录。
示例:事务A第一次读取数据生成ReadView后,事务B的修改或插入会被阻塞,直到事务A提交。
例外情况:若事务先执行UPDATE(当前读)再SELECT,可能因UPDATE修改了不可见记录而导致幻读。
SERIALIZABLE(串行化)
所有操作均通过加锁(记录锁+间隙锁+临键锁)实现,事务串行执行,完全避免脏读、不可重复读和幻读。
性能最低,适用于对一致性要求极高的场景。
RC:适合读多写少、允许不可重复读但要求避免脏读的场景。
RR:默认隔离级别,平衡一致性与并发性能,适合大多数业务场景。
SERIALIZABLE:仅在极端一致性要求下使用,如金融交易。
MySQL事务通过MVCC和锁机制实现高效并发控制: