log日志

binlog

binlog 为二进制格式的数据,用于备份数据库的数据。
用于复制,在主从复制中,从库利用主库上的 binlog 进行重播,实现主从同步。 
用于数据库的基于时间点的还原。

binlog 是属于 MySQL Server 层面的,又称为归档日志,属于逻辑日志,是以二进制的形式记录的是这个语句的原始逻辑,依靠 binlog 是没有 crash-safe 能力的。

三种模式:

  1. statement:基于 SQL 语句的模式,某些语句中含有一些函数,例如 UUID NOW 等在复制过程可能导致数据不一致甚至出错。
  2. row:基于行的模式,记录的是行的变化,很安全。但是 binlog 的磁盘占用会比其他两种模式大很多,在一些大表中清除大量数据时在 binlog 中会生成很多条语句,可能导致从库延迟变大。
  3. mixed:混合模式,根据语句来选用是 statement 还是 row 模式。

undo log

undo log 是回退日志,提供回退操作。是逻辑日志。
undo 用来回滚行记录到某个版本。undo log 一般是逻辑日志,根据每行记录进行记录。
保存了事务发生之前的数据的一个版本,可以用于回滚,同时可以提供多版本并发控制下的读(MVCC),也即非锁定读。

缺陷:
  • 事务提交前需要将 Undo Log 写磁盘(提供可回滚功能,保证原子性),这会造成多次磁盘 IO(不考虑各种优化例如 SQL 解析优化等),这些 IO 算是顺序 IO;
  • 事务提交后需要将数据立即更新到数据库中,这又会造成至少一次磁盘 IO,这是一次随机 IO。
解决:

事务提交后如果能够将数据缓存一段时间,而不是立即更新到数据库,就能将一次次的随机 IO 打包变成一次 IO,可以提高性能。但是这样就会丧失事务的持久性。因此引入了另外一种机制来实现持久化,即 redo log。redo 解决的问题之一就是事务执行过程中的强制刷脏。
在事务提交前,只要将 Redo Log 持久化即可,不需要将数据持久化。当系统崩溃时,虽然数据没有持久化,但是 Redo Log 已经持久化。系统可以根据 Redo Log 的内容,将所有数据恢复到最新的状态。


redo log

redo log 是重做日志,提供前滚操作。是物理日志。

redo log 通常是物理日志,记录的是数据也页物理修改,而不是某一行或某几行修改成怎样怎样,它用来恢复提交后的物理数据页(恢复数据页,且只能恢复到最后一次提交的位置)。

确保事务的持久性。防止在发生故障的时间点,尚有脏页未写入磁盘,在重启 mysql 服务的时候,根据 redo log 进行重做,从而达到事务的持久性这一特性。

redo log 是 InnoDB 存储引擎层的日志,又称重做日志文件,用于记录事务操作的变化,记录的是数据修改之后的值,不管事务是否提交都会记录下来。在实例和介质失败(media failure)时,redo log 文件就能派上用场,如数据库掉电,InnoDB 存储引擎会使用 redo log 恢复到掉电前的时刻,以此来保证数据的完整性。

在一条更新语句进行执行的时候,InnoDB 引擎会把更新记录写到 redo log 日志中,然后更新内存,此时算是语句执行完了,然后在空闲的时候或者是按照设定的更新策略将 redo log 中的内容更新到磁盘中,这里涉及到 WAL 即 Write-Ahead-logging 技术,他的关键点是先写日志,再写磁盘。

有了 redo log 日志,那么在数据库进行异常重启的时候,可以根据 redo log 日志进行恢复,也就达到了 cash-safe。
redo log 日志的大小是固定的,即记录满了以后就从头循环写。


关于事务:

将 undo log 和 redo log 结合起来,提升效率。

要从两个角度来优化,一个就是尽可能减少写入硬盘(即多个事务合并成一次落盘),另一个就是尽量顺序写入(HDD 的随机写入性能远差于顺序写入)。

Undo 记录某数据被修改前的值,可以用来在事务失败时进行 rollback;
Redo 记录某数据块被修改后的值,可以用来恢复未写入 data file 的已成功事务更新的数据。

  • Redo Log 保证事务的持久性。
  • Undo Log 保证事务的原子性(在 InnoDB 引擎中,还用 Undo Log 来实现 MVCC)。

比如某一时刻数据库 DOWN 机了,有两个事务,一个事务已经提交,另一个事务正在处理。数据库重启的时候就要根据日志进行前滚及回滚,把已提交事务的更改写到数据文件,未提交事务的更改恢复到事务开始前的状态。即,当数据 crash-recovery 时,通过 redo log 将所有已经在存储引擎内部提交的事务应用 redo log 恢复,所有已经 prepared 但是没有 commit 的 transactions 将会应用 undo log 做 roll back。

单独使用:

  1. 假设只有 undo-log:那么就必须保证提交前刷脏完成,否则宕机时有些修改就在内存中丢失了,破坏了持久性。(这样带来了一个问题,那就是前面提到的性能差)。
  2. 假设只有 redo-log:那么就不能随心所欲地在事务提交前刷脏,即无法支持大事务。(假如、某张表有 100 亿的 8 字节整数数据,就算不考虑其他东西带来的损耗,光 update 整张表至少要消耗 80G 的内存。如前所述,有了 undo-log,就可以随便刷脏。)

区别:

  1. 层次不同;redo/undo 是 innodb 引擎层维护的,而 binlog 是 mysql server 层维护的,跟采用何种引擎没有关系,记录的是所有引擎的更新操作的日志记录。
  2. 记录内容不同;记录内容不同。redo/undo 记录的是 每个页/每个数据 的修改情况,属于物理日志+逻辑日志结合的方式(redo log 是物理日志,undo log 是逻辑日志)。binlog 记录的都是事务操作内容,记录的是更新语句的原始逻辑。
  3. 记录时机不同;redo/undo 在 事务执行过程中 会不断的写入,而 binlog 是在 事务最终提交前 写入的。binlog 什么时候刷新到磁盘跟参数 sync_binlog 相关。
  4. redo log 是循环写,日志空间大小固定;binlog 是追加写,是指一份写到一定大小的时候会更换下一个文件,不会覆盖。
  5. binlog 可以作为恢复数据使用,主从复制搭建,redo log 作为异常宕机或者介质故障后的数据恢复使用。

理解:

原有逻辑:
新逻辑:
原有的每次提交事务前同步数据并同步 undolog,会造成大量的磁盘 IO,特别是同步数据是随机 IO,效率低下。
在新逻辑中,更改数据的时候同步更改 redolog,将更改的数据缓存在缓冲区中,提交前,同步 redolog 和 undolog,因为 log 同步都是顺序 IO,提升效率。即使断电等数据丢失,未提交的数据在 undolog 中,可以进行 rollback,而已经提交的数据在 redolog 中,可以根据其恢复。而对于更改的数据,间隔时间过后在进行同步,减少数据同步次数来提升效率。