November 19, 2018
今天刚好看到了 MySQL 中日志系统的设计,谈谈自己的理解。
mysql 中有两个十分重要的日志模块 —— redo log 和 binlog。
顾名思义,是重做日志。redo log 是由 InnoDB 引擎实现的。
当有一条记录需要更新时,InnoDB 会把记录写到 redo log 里,并更新内存,更新就算完成了。之后 InnoDB 会在空闲的时候,把日志里的操作记录拿出来,更新到磁盘上。
这种技术就是 WAL - Write-Ahead Logging,即先写日志再写磁盘。
首先如果没有 redo log ,更新操作是这样的:客户端发起更新请求 -> InnoDB 开始处理更新 -> 先从磁盘中找到对应的记录 -> 更新这条记录到磁盘中。整个过程 I/O 成本、查找成本都很高。
而有了 redo log,InnoDB 当下不需要到磁盘中查找对应的记录,只需要把这条更新行为记录到日志中,并更新内存中的数据即可。然后等空闲的时候,再从 redo log 中拿出那些待处理的日志开始处理,这中间甚至可能会有一些重复的操作,也可以顺便进行合并,效率提高了不是一点点啊。
InnoDB 的 redo log 是固定大小的,也就是说一旦写满了,InnoDB 就需要提前开始清算工作,把一部分日志对应的操作落实到磁盘上,以便释放这部分空间让后面的日志能够写进来。
有了 redo log,InnoDB 就能够应对异常重启问题,之前提交的记录都不会丢失,这个能力称为 crashed-safe。
redo log 属于 InnoDB 引擎层的日志,是物理日志,而 binlog 属于 mysql server 层面的日志,是逻辑日志。
binlog 记录的是原始操作,并且可以不断追加写入,不需要覆盖以前的日志
一个数据的更新操作可以描述如下:
这里使用到了两阶段提交,来保证事务的一致性。 也就是说,redo log 所记录的行为必须与 binlog 所记录的行为一致才行,两个日志不一致,最终一定会导致数据不一致。
日志可以用来重放某一时间段内发生的事情,保留日志我们能够复原现场。
关于 mysql 日志的知识点是从专栏 —— MySQL实战45讲 中看到的,作者原文讲的很棒,推荐你也去订阅看看。
痕迹
没有过去,就没法认定现在的自己