MySQL面试题 事务实现全解析:Undo Log、Redo Log、锁与 MVCC 协同机制详解

MySQL是如何实现事务的?

MySQL有四大特性分别是原子性一致性持久性隔离性

MySQL实现事务靠Undo logRedo logMVCC这四个核心组件来实现的

  1. 通过Undo log来实现原子性,在进行写操作之前,会把原来的数据存入Undo log中,当事务回滚时,通过Undo log进行反向操作,把数据恢复回去。
  2. 通过Redo log 来实现持久性,在进行写操作时,不会直接把数据写入磁盘数据页,而是先写入Redo log,就算写入磁盘数据页宕机了,也能通过重做Redo log来恢复数据。
  3. 通过锁机制来实现写的隔离性,当两个事务同时改一个数据时,必须一个等另一个释放锁,InnoDB支持行锁,间隙锁防止幻读。
  4. 通过MVCC来实现读写的隔离性,读的时候不加锁,而是通过Undo log版本链来找到自己读的数据版本,读的时候能写,写的时候也能读。

Redo log的工作原理

  • InnoDB在写入数据时,不会直接把数据写入磁盘的数据页,因为这样做随机磁盘IO太多,性能不好,而是先把数据顺序写入Redo log中,再找时间把数据页刷到磁盘上,应为顺序写比随机写快。
  • redo log是通过循环写来实现的,redo log中有两个指针,一个记录写到哪里了,一个记录刷盘刷到哪里了,两指针之间就是待刷盘的脏数据。
  • 事务提交时,redo log必须落盘,这个行为由 innodb_flush_log_at_trx_commit 控制:
    • 设置成1,每次提交都要刷盘
    • 设置成0,每一秒刷一次盘,宕机可能造成一秒的数据丢失
    • 设置成2,把数据写到系统缓存中,MySQL宕机不丢失,服务器挂了才丢。

Undo log与版本链

  1. 数据库每条记录都有两个隐藏字段:
    • trx_id:记录最后修改这个数据的事务ID
    • roll_pointer:指向undo log里的上一个版本
  2. 多次修改就会形成一个版本链
  3. MVCC在读数据时,会根据事务的ReadView去沿着版本链去往回找。
  4. 在读未提交的事务隔离级别下,每次访问都会生成新的ReadView;在读已提交下,事务开始时会生成ReadView,以后每次访问都用这个。

事务提交的两个阶段

InnoDB和Server层各有自己的日志,redo log 和bin log,为了保证两个日志的一致性,所以用到了两个阶段。

  1. 准备阶段:redo log写盘,然后把状态改为prepare
  2. 提交阶段:bin log写盘,然后redo log状态改为commit
    如果是bin log写入前宕机,redo log的状态为prepare,但是没有对应的bin log,则触发回滚
    如果是bin log写入后宕机,redo log的状态为prepare,有对对应的bin log,则会触发事务提交
    这一套机制保护了主从复制的数据一致性,主表靠redo log数据恢复,从表靠bin log数据同步。

锁的实现细节

InnoDB的行锁是加在索引上的,如果修改数据时没有走索引,就会锁住整张表

InnoDB有三种行锁:

  • 普通的行锁,锁整行数据
  • 间隙锁:锁一个区间,不包含数据本身
  • 临键锁(行锁+间隙锁):锁整行数据+数据前面的区间

MVCC是什么

MVCC是多版本并发控制,核心思想是让读写互不阻塞:写操作会产生新的版本,读操作会根据事务的ReadView在Undo log的版本链上找到自己版本的数据。

  • 表中的每条数据都有两个隐藏字段,一个记录当前事务ID,一个记录undo log
  • 每次写操作,都会先把旧的值写入undo log,再把新的值写入磁盘数据页,回滚指针指向旧版本,这样就形成了一个数据链。
  • 普通的读都是快照读,不加锁,直接通过版本链找到自己对应的数据直接返回。

MySQL 中的日志类型有哪些?bin log、redo log 和 undo log 的作用和区别是什么?

MySQL 有三种核心日志。bin log 负责主从复制和数据恢复,redo log 保证崩溃后数据不丢,undo log 支撑事务回滚和 MVCC。

  • bin log 是 Server 层的日志,记录的是逻辑操作,也就是原始 SQL 或者行变更前后的值。它的核心场景是主从同步,从库拉取主库的 bin log 重放一遍就能保持数据一致。另外做数据恢复的时候,也是靠 bin log 配合全量备份回放到指定时间点。

  • redo log 是 InnoDB 引擎独有的,记录的是物理变更,具体就是"某个数据页的某个偏移量改成了什么值"。它的作用是 MySQL 挂了重启后,InnoDB 会用 redo log 把没来得及刷盘的脏页恢复出来。redo log 是循环写的,空间固定,写满了就得等 checkpoint 推进才能继续。

  • undo log 也是 InnoDB 的,记录的是数据修改前的旧值。事务回滚的时候,就靠 undo log 把数据改回去。另外 MVCC 的快照读也依赖它,别的事务要读历史版本,顺着 undo log 链往前找就行。

相关推荐
Database_Cool_2 小时前
阿里云 RDS MySQL 降本增效实战:从规格选型到成本优化,月成本降低64%全攻略
mysql·阿里云·云计算
java_logo2 小时前
Apache Doris Docker 部署指南:实时分析数据库实战
数据库·docker·apache·doris·apache doris·轩辕镜像·docker部署doris
广州灵眸科技有限公司9 小时前
xfce桌面触摸校准:基于灵眸科技EASY-EAl-Orin-Nano
数据库·windows·科技
Cloud云卷云舒11 小时前
云卷云舒:从Oracle/MySQL迁移到HaishanDB:迁移评估工具核心技术拆解
mysql·oracle·ai-native·haishandb·信创数据库替换
憧憬成为web高手12 小时前
皮卡丘靶场速通--sql 2
数据库·sql·mybatis
段一凡-华北理工大学12 小时前
向量数据库实战:选型、调优与落地~系列文章12:文本分块策略实战:chunk_size 怎么选?重叠多少?
开发语言·数据库·后端·oracle·rust·工业智能体·高炉智能化
oradh14 小时前
Oracle XTTS实现跨版本迁移和升级(Oracle 11g单库升级至19C RAC集群)
数据库·oracle·11g升级19c·xtts跨版本迁移和升级
用户713335851562414 小时前
MySQL - 事务、redo/undo 日志与 MVCC
mysql
z1234567898615 小时前
2026最新两款AI编程工具深度对比实测
java·数据库·ai编程
程序猿DD15 小时前
一个 API Key,统一调用大模型、生图和联网搜索
数据库·网关