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

MySQL是如何实现事务的?

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

MySQL实现事务靠Undo log、Redo log、锁、MVCC这四个核心组件来实现的

  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 链往前找就行。

相关推荐
这个DBA有点耶5 分钟前
研发规模/投入最大的国产数据库厂商是谁?拆解五个衡量维度
数据库·程序员·产品
葡萄城技术团队33 分钟前
数据库里的数据明明是对的,为什么 BI 报表还是错?
数据库
野生数据人33 分钟前
日志平台每日巡检我压成了一条命令链:从 SHOW BACKENDS 到扩缩容的完整步骤
大数据·数据库
bmxy小明同学1 小时前
2026-10-09-token与成本
java·前端·数据库
路远的数据库笔记1 小时前
Oracle报ORA-00020连接打满?从专用进程模型到静态参数,一次生产排查全记录
数据库·oracle·国产数据库·ora-00020·dba实战·sharedserver
瀚高PG实验室1 小时前
瀚高数据库序列介绍、使用及值不连续、重复写入等现象处理
数据库·postgresql·瀚高数据库
这个DBA有点耶1 小时前
PostgreSQL HOT更新:频繁更新表的索引膨胀根因与fillfactor调优
数据库·sql·postgresql
野生数据人1 小时前
日志平台运维速查表:巡检命令、阈值、参数,一张贴墙
大数据·数据库
数据库小学妹1 小时前
向量检索最小可运行实现:HNSW索引参数与召回率/延迟权衡
数据库·后端
发量惊人的中年网工2 小时前
SD-WAN 组网方案怎么选?跨地域与多分支企业的选型指南(含成本对比)
服务器·网络·数据库