日志的目的在于记录修改,保证事务的原子性(记录事务中的多个修改,同步到磁盘中),持久性(确保修改不会丢失)
详解

redo log

innodb 引擎独有的日志模块,用于快速记录某个数据页上产生的修改,之后系统线程将数据同步到磁盘空间,意味着只要写入到redo log中数据就不会丢失,保证了事务的持久性

设计目标

redo log 能保证对于已经COMMIT的事务产生的数据变更,即使是系统宕机崩溃也可以通过它来进行数据重做,达到数据的一致性,这也就是事务持久性的特征,一旦事务成功提交后,只要修改的数据都会进行持久化,不会因为异常、宕机而造成数据错误或丢失,所以解决异常、宕机而可能造成数据错误或丢是redo log的核心职责

记录内容

redo log 中记录的是某页数据产生的修改,写入到innodb预设的文件中去,这个文件的大小固定(物理地址连续),这样系统无需分配新空间写入速度快

写入策略

WechatIMG81.png
除了上面几种机制外,还有其它两种情况会把redo log buffer中的日志刷到磁盘。
1、定时处理:有线程会定时(每隔 1 秒)把redo log buffer中的数据刷盘。
2、根据空间处理:redo log buffer 占用到了一定程度( innodb_log_buffer_size 设置的值一半)占,这个时候也会把redo log buffer中的数据刷盘。

undo log

事务可以进行回滚从而保证事务操作原子性是通过undo log 来保证的,要对事务数据回滚到历史的数据状态,所以我们也能猜到undo log是保存的是数据的历史版本,通过历史版本让数据在任何时候都可以回滚到某一个事务开始之前的状态。undo log除了进行事务回滚的日志外还有一个作用,就是为数据库提供MVCC多版本数据读的功能

记录内容

在Mysql里数据每次修改前,都首先会把修改之前的数据作为历史保存一份到undo log里面的,数据里面会记录操作该数据的事务ID,然后我们可以通过事务ID来对数据进行回滚

image.png
在写入数据前会记录当前数据,写入成功之后会将成功

bin log

mysql层面的修改记录,他记录了所有修改语句,在进行mysql主从时很重要

image.png

设计目标

binlog 是作为mysql操作记录归档的日志,这个日志记录了所有对数据库的数据、表结构、索引等等变更的操作(不包括查询)。也就是说只要是对数据库有变更的操作都会记录到binlog里面来, 可以把数据库的数据当成我们银行账户里的余额,而binlog就相当于我们银行卡的流水。账户余额只是一个结果,至于这个结果怎么来的,那就必须得看流水了。而同样在mysql里我们就是通过binlog来归档、验证、恢复、同步数据

记录内容

binlog不仅记录了操作的语句,同时还记录了语句所执行的消耗的时间。

binlog 有三种记录格式,分别是ROW、STATEMENT、MIXED

1、ROW: 基于变更的数据行进行记录,如果一个update语句修改一百行数据,那么这种模式下就会记录100行对应的记录日志。
2、STATEMENT:基于SQL语句级别的记录日志,相对于ROW模式,STATEMENT模式下只会记录这个update 的语句。所以此模式下会非常节省日志空间,也避免着大量的IO操作。
3、MIXED: 混合模式,此模式是ROW模式和STATEMENT模式的混合体,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则采用row格式保存binlog。
这三种模式需要注意的是:使用 row 格式的 binlog 时,在进行数据同步或恢复的时候不一致的问题更容易被发现,因为它是基于数据行记录的。而使用 mixed 或者 statement 格式的 binlog 时,很多事务操作都是基于SQL逻辑记录,我们都知道一个SQL在不同的时间点执行它们产生的数据变化和影响是不一样的,所以这种情况下,数据同步或恢复的时候就容易出现不一致的情况

写入策略

在进行事务的过程中,首先会把binlog 写入到binlog cache中(因为写入到cache中会比较快,一个事务通常会有多个操作,避免每个操作都直接写磁盘导致性能降低),事务最终提交的时候再吧binlog 写入到磁盘中。当然事务在最终commit的时候binlog是否马上写入到磁盘中是由参数 sync_binlog 配置来决定的。

1、sync_binlog=0 的时候,表示每次提交事务binlog不会马上写入到磁盘,而是先写到page cache,相对于磁盘写入来说写page cache要快得多,不过在Mysql 崩溃的时候会有丢失日志的风险。
2、sync_binlog=1 的时候,表示每次提交事务都会执行 fsync 写入到磁盘 ;
3、sync_binlog的值大于1 的时候,表示每次提交事务都 先写到page cach,只有等到积累了N个事务之后才filesystem写入到磁盘,同样在此设置下Mysql 崩溃的时候会有丢失N个事务日志的风险。

很显然三种模式下,sync_binlog=1 是强一致的选择,选择0或者N的情况下在极端情况下就会有丢失日志的风险,具体选择什么模式还是得看系统对于一致性的要求

redo log对比

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