Mysql(四)-日志系统

Mysql为什么会有日志系统?

  我们知道,mysql的数据是存储在磁盘的,每次更新数据需要先进入磁盘,然后在磁盘中找到需要更新的数据,这样会产生IO成本以及查找成本,这样会大大降低Mysql的性能。

所以mysql就采用先存入日志文件,当系统空闲的时候,mysql再通过日志文件将数据存入磁盘。当然日志文件还要其他的作用,比如主从模式下,保证主库和丛库的数据一致性,

也会用到日志文件(binlog),Mysql的两大日志模块分别为redo log以及binlog,redo log是InnoDB引擎独有的,而binlog是Server自带的。下面我们来详细讲讲这两个日志模块。

redo log

  redo log是InnoDB存储引擎独有的,它记录的是物理操作,比如在某个数据页上做了什么修改。

  redo log是固定大小的,比如可以配置一组4个文件,每个文件大小为1G,它会循环写入。也就是说这种配置最多只能保存4个G的日志,当日志满了之后,会从第一个

文件开始覆盖以前的日志。覆盖日志之前,要保证被覆盖的日志对应的数据已经更新到磁盘。

  有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。

binlog

  binlog是Server提供的归档日志,所以的存储引擎都支持,它记录的是语句的原始逻辑,比如给id=1的一行的a字段加2。

  binlog可以实现数据库的数据恢复,比如恢复到指定的某个时刻的数据,还可以通过binlog实现主从数据库的数据一致性。

redo log和binlog比较

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
  2. redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
  3. redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。

从简单语句的执行流程来看redo log和binlog的存储逻辑

  有了对这两个日志的概念性理解,我们再来看执行器和 InnoDB 引擎在执行这个简单的 update 语句时的内部流程。我们以mysql> update T set c=c+1 where ID=2;为例

  1. 执行器先找引擎取 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。如果 ID=2 这一行所在的数据页本来就在内存中,就直接返回给执行器;否则,需要先从磁盘读入内存,然后再返回。
  2. 执行器拿到引擎给的行数据,把这个值加上 1,比如原来是 N,现在就是 N+1,得到新的一行数据,再调用引擎接口写入这行新数据。
  3. 引擎将这行新数据更新到内存中,同时将这个更新操作记录到 redo log 里面,此时 redo log 处于 prepare 状态。然后告知执行器执行完成了,随时可以提交事务。
  4. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘。
  5. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成提交(commit)状态,更新完成。
原文地址:https://www.cnblogs.com/liu-yi/p/14349019.html