一、Redo Log
在MySQL存储引擎的底部是物理存储层,它是文件的物理存储层(包括二进制日志、数据文件、错误日志、慢查询日志、完整日志、redo/undo 日志等)。
1、什么是redo log
在MySQL中,如果每次更新操作都需要写入磁盘,那么磁盘也必须找到相应的记录,然后进行更新。整个过程的 IO 成本和搜索成本都很高。
为了解决这个问题,MySQL中经常提到的WAL技术,WAL的全称是Write Ahead Logging(提前写入日志)。它的关键点是首先写入日志,然后写入磁盘
具体来说,当需要更新记录时,InnoDB引擎将首先将记录写入重做日志并更新内存。此时,更新完成。同时,InnoDB引擎会在适当的时候将此操作记录更新到磁盘,此更新通常在系统空闲时完成。
2、redo log工作原理解析
Redo log 是一个循环重用的文件集,负责记录 InnoDB 存储引擎中缓冲池(Buffer Pool)的所有物理修改日志。
提交事务时,日志缓冲区 log buffer 将刷新为 Redo log 日志文件。
当检查点位置的 LSN 和最新写入的 LSN 差值(checkpoint_age)达到总 Redo log 日志空间的 75% 时,InnoDB 存储引擎将执行异步刷新操作,直到其降至75%以下,并释放重做日志空间。
当 checkpoint_age 达到总文件大小的 90% 时,将触发同步刷新。此时,InnoDB处于暂停状态,无法运行。
write pos 写入位置是当前记录的位置。它在书写时向后移动。写入3号文件的末尾后,将返回0号文件的开头。checkpoint 检查点是要擦除的当前位置。它也向后移动并循环。在擦除记录之前,应将记录更新为数据文件。
write pos 写入位置和 checkpoint 检查点之间是的空白部分,可以用来记录新的操作。如果写入pos 赶上了检查点 checkpoint,则意味着 Redo log 已满,此时无法执行新的更新。相反,停止并擦除一些记录以推进 checkpoint 。
通过 Redo log 日志,InnoDB可以确保即使数据库异常重启,之前提交的记录也不会丢失。这种能力称为 crash-safe (碰撞安全)。
3、redo log 如何设置
Redo log 日志的大小直接影响数据库的处理能力,如果设置太小,强制检查点 checkpoint 操作将频繁刷新脏页。
InnoDB 的 Redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,总共就可以记录 4GB 的操作,从头开始写,写到末尾就又回到开头循环写。
最后我们需要将重做日志设置为更大的大小。在5.6版之前,Redo log 日志的总大小不能超过3.8GB。5.7版之后,此限制被释放。由于它太小而无法影响性能,所以将其设置为尽可能大是否更好?
二、Bin Log
MySQL有两个部分:一个是引擎层,负责与存储相关的具体事宜。我们上面讨论的 Redo log 日志是 InnoDB引擎的一个独特日志,
一个是服务器层,它主要在MySQL服务器层做事情,服务器层日志,称为 Bin Log(归档日志) 。
MySQL期初没有 InnoDB 存储引擎。MySQL自己的引擎是 MyISAM,但 MyISAM 没有崩溃安全功能,Bin log 日志只能用于存档。
三、InnoDB执行与Log系统的关系
执行此更新语句时,执行器和InnoDB引擎的内部工作原理:
一、执行器首先查找引擎以获得行。ID是主键,引擎直接使用树搜索来查找该行。
如果该行的数据页已经在内存中,它将直接返回到执行器;否则,您需要在返回之前从磁盘读取内存。
二、执行器获取引擎给出的行数据,将1加到该值上,获取一行新数据,然后调用引擎接口写入新数据行。
三、引擎将新数据更新到内存,并将更新操作记录在重做日志中。此时,重做日志处于准备状态。然后告诉执行者执行已完成,事务可以随时提交。
四、执行器为该操作生成 Bin Log,并将 Bin Log 归档日志写入磁盘。
五、MySQL 执行器调用引擎的提交事务接口,引擎将刚刚写入的 Redo Log 日志更改为提交状态,更新完成。
2、两阶段提交
流程图中可以看到,MySQL InnoDB 将 Redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"。
Redo log 和 Bin Log 都可以用来指示事务的提交状态。两阶段提交是为了保持两种状态的逻辑一致。
四、 Redo log 与 Bin Log 区别
Redo log 重做日志对于InnoDB引擎是唯一的;Binlog 归档位置是在MySQL的服务器层上实现的,可以被所有引擎使用。
Redo log 是一个物理日志,记录对数据页所做的更改;Bin log是记录语句原始逻辑的逻辑日志。
Redo log 是循环写入的,空间会用完;可以附加 Bin log,Bin log 文件在写入到一定大小后将切换到下一个,并且不会覆盖上一个日志。
五、Undo Log
1、什么是 Undo Log
物理层在逻辑上分为系统表空间、用户表空间和 Undi Log 日志。
系统表空间包含 ibdata 文件和一些 Undo文件。ibdata文件包含 insert buffer 插入缓冲区段、 double write 双写段、回滚段、索引段、数据字典段和 Undo 信息段。
MySQL 5.7的新特性如下:Undo 撤销与共享表空间的 ibdata 文件分离。您可以在安装MySQL时自行指定文件大小和编号。
MySQL 8.0的新特性如下:InnoDB表的数据字典和 Undo 与共享表空间 ibdata 完全分离。此前,ibdata 文件中的数据字典需要与独立表空间ibd文件中的数据库字典保持一致。
2、Write Ahead Logging(WAL)
首先写入日志,然后写入磁盘。成功写入日志后,事务不会丢失。
稍后,检查点机制将确保磁盘物理文件和重做日志之间的一致性;
使用 Redo Log 记录更改的数据,即使用 Redo Log 来记录交易数据的更改值;
使用 Undo Log 记录更改前的数据,也就是说,Undo Log 将记录事务数据更改前的值,以便回滚和多版本读取其他事务。
六、事务的四大特性与Log系统的关系
事务的 ACID 都需要通过 Redo、Undo 日志来保证等。
原子性: 原子性与 WAL 有很大的关系。需要从 Redo 重做日志恢复的数据。如果事务没有提交,缓冲池的脏页被刷新,那么不应该存在的数据怎么会消失?它需要通过撤销来实现,这是通过 Undo 重做来保证的。因此,最终原子性由 Redo 的 WAL 机制保证。
持久性: 一旦事务通过原子性提交,即使在停机的情况下,也可以从逻辑上检索数据,然后再次写入物理存储空间。这确保了数据不会从逻辑和物理方面(即数据库的持久性)丢失。
隔离性: 指事务的执行不能受到其他事务的干扰,即事务中使用的操作和数据与其他并发事务隔离。锁定和多版本控制符合隔离。MVCC多版本实现有三个隐藏字段。回滚指针(DB_ROLL_PT)指向当前记录项的 Rollback Segment 的 Undo log日志记录,通过该记录可以找到以前版本的数据。
总结
本文主要详解MySQL数据库中 Redo log(重做日志)、 Bin Log (归档日志)、Uudo Log(撤销日志),以及 Log 与 InnoDB 的关系和区别,和MySQL事务特性的底层原理。