innodb存储引擎如何实现事务_mysql事务支持原理

2次阅读

innodb通过mvcc、undo log、redo log、锁机制和两阶段提交协同实现acid:undo log保障原子性与一致性读,redo log确保持久性,行级锁与mvcc共同支撑隔离性,2pc协调binlog与redo log以保证崩溃恢复一致性。

innodb存储引擎如何实现事务_mysql事务支持原理

InnoDB 通过多版本并发控制(MVCC)、undo log、redo log、锁机制和两阶段提交(2PC)协同实现事务的 ACID 特性。它不是靠单一组件,而是多个模块紧密配合:undo log 保证回滚与一致性读,redo log 确保持久性,行级锁+意向锁支撑隔离性,而事务状态管理和崩溃恢复逻辑则由事务子系统统一协调。

undo log:支撑原子性与一致性读的核心

每次修改数据前,InnoDB 先将原始数据写入 undo log。这样:

  • 事务回滚时,直接用 undo log 中的旧值覆盖当前记录,实现原子性;
  • 在 RC(读已提交)或 RR(可重复读)隔离级别下,select 不加锁查询会依据事务启动时的 read view,从 undo log 链中找到对应版本的数据,实现非阻塞的一致性读;
  • undo log 分为 insert undo 和 update/delete undo,前者在事务提交后可立即清理,后者需等待 purge 线程判断是否还有活跃事务依赖。

redo log:保障持久性的关键日志

redo log 是物理日志,记录“在某个数据页的某个偏移位置做了什么修改”。它的作用是:

  • 事务提交时只需确保 redo log 持久落盘(write + fsync),不必等脏页刷磁盘,大幅提升性能;
  • mysql 崩溃重启后,通过重放 redo log,能把已提交但未写入数据文件的修改补全,满足持久性;
  • redo log 是循环写入的固定大小文件组(如 ib_logfile0/ib_logfile1),通过 checkpoint 机制协调刷脏页进度,避免覆盖尚未应用的日志。

锁与 MVCC:共同实现隔离性

InnoDB 默认使用行锁(Record Lock)、间隙锁(Gap Lock)和临键锁(Next-Key Lock),结合 MVCC 实现不同隔离级别:

  • RR 级别下,普通 SELECT 使用快照读(不加锁,走 MVCC),UPDATE/DELETE/SELECT for UPDATE 则加临键锁防止幻读;
  • 唯一索引等值查询只锁匹配行;范围查询或非唯一索引会触发间隙锁,封锁索引区间;
  • 意向锁(IS/IX)是表级轻量锁,用于快速判断表中是否有行锁,避免全表检测,提升 DML 并发效率。

事务提交与崩溃恢复:两阶段提交与事务状态管理

为了保证 binlog 与 redo log 的一致性(尤其在主从复制场景),InnoDB 在事务提交时采用内部两阶段提交:

  • prepare 阶段:将事务状态设为 PREPARE,并把 XID 写入 redo log;
  • write binlog:MySQL Server 层将该事务的 binlog 写入文件;
  • commit 阶段:InnoDB 将事务状态改为 COMMIT,并完成 redo log 的 commit 标记。

崩溃恢复时,MySQL 启动时扫描 redo log:遇到 prepare 但无 commit 的事务,会检查 binlog 是否完整——若存在对应 binlog,则提交;否则回滚,确保主从数据一致。

不复杂但容易忽略:事务的生命期由 begin(隐式或显式)开始,到 commit 或 rollback 结束;期间所有 DML 操作都受上述机制约束。真正理解事务,关键是把 undo、redo、锁、read view 和 XID 这几条线串起来看。

text=ZqhQzanResources