宽泛地谈谈 Mysql 事务

gomkiri 发布于 2025-10-28 131 次阅读


本文章内容均以 Mysql 和存储引擎 InnoDB 来展开。

事务

一提到事务,首先大伙能想到的就是 ACID,四个字母分别代表原子性、一致性、隔离性和持久性。如果你已经较为完整的学习过一次Mysql事务,自然可以回忆起原子性的实现离不开 undo Log , 隔离性和 MVCC 的脱不了干系、一说持久性就会想到 redo log了,而这个一致性更是重量级,他不依靠具体的实现方法,而是又原子性、隔离性和持久性来通过支撑的。

在展开之前,我们还需要回忆两个概念,那就是事务隔离级别和可能出现的并发问题:在事务隔离级别中读未提交作为一个最低的等级解决不了任何并发问题;然后是读已提交,它可以解决脏读问题;后为可重复读,可重复的有一个特殊点是:他不仅借助 MVCC 解决了不可重复读问题和快照读状态下的幻读问题,还使用一系列的锁去解决了当前读状态下的幻读问题;最后是最安全但是效率最低的串行化,它使用一种类似于单线程的方式来解决所有的并发问题,而代价就是性能大打折扣。

Undo Log由多个 Undo Record 组合而成的回滚日志,主要是用于事务管理和 MVCC,使用单独的 undo log表来进行存储。

在进行事务管理时,事务提交之前我们必须对事务中的每个操作都进行记录,记录的形式可以有两种,分别是先记录每一条语句,等事务提交的时候在统一执行,但是这么做肯定会造成很大的磁盘随机IO;另一种方式就是使用 undo log,每条语句都会立即执行同时在 undo log 中去记录该如何回到上一步,如果事务执行失败就按照 undo log 插入的反顺序再执行一遍即可。

MVCC,又称多版本并发控制,其核心就是 ReadView 视图和 Undo Log日志。在合适的时机去创建ReadView 视图,在使用时通过 ReadView 和每个数据 Undo Log 的记录在比较,如果发现当前数据在这个 ReadView 中不可见,那就通过 Undo Log 进行数据回退,直到能够找到可见的数据或者是这条记录完全不可见。

Redo log,为了可以能够提高 InnoDB 的读写效率,Mysql 也要使用内存,也就是常说的 Buufer Pool,既然要加一层内存,我们就要考虑数据如何存储到硬盘,这时就设计了 Redo Log 日志,当有数据写入时,首先将数据写入到 Redo Log 中,通过两阶段提交的方式保存到硬盘中。

既然上面提到了日志,那么就在补充两种日志:bin log & relay log,即二进制日志和中继日志,其中的 bin log 是以二进制的方式存储数据库的数据记录,可以以较小的空间存储较多的数据,所以我们可以使用bin log 来完成数据库的备份,同时在 Mysql 的主从架构中,主从复制也是通过 bin log来完成的,但是在同步过程中,从机写入 bin log 需要时间,这段时间主机可能会有新的数据写入,这个时候就用到了 Relay Log ,主机将这段时间的新变动写入到 Relay Log 中,从机写入 bin log 完成后再读取 Relay Log 中的数据。

参考

  1. 庖丁解InnoDB之Undo LOG
  2. 庖丁解InnoDB之REDO LOG
  3. 小林Coding

小码农 & GPT调教糕手
最后更新于 2025-10-29