日志体系

MySQL为了满足主从复制、事务等,有复杂的日志体系。
MySQL的日志体系不是主要不是用来看的,而是运行必要的。
日志的种类有:

  • Server层产生binlog,用来进行数据复制
  • InnoDB产生undo log、redo log,用来实现事务ACID

    binlog 归档日志

  • Binlog是server层产生的逻辑日志

  • 用来进行数据复制和数据传送
  • Binlog完整记录了数据库每次的数据操作,可作为数据闪回手段
  • Binlog记录在专门的文件中

    undo log 回滚日志

  • lnnoDB自身产生的逻辑日志,用于事务回滚和展示旧版本

  • 对任何数据(缓存)的更新,都先写undo log
  • undo log位于表空间的undo segment中
  • SQL: UPDATE name = ‘b’ → undo: UPDATE name = ‘a’

    • 需要把表数据的name字段改为’b’, 原始表中数据name字段为 ‘a’
    • undo log 就是记录与执行SQL相反的日志,如果语句执行失败,
      执行这条回滚SQL数据即可恢复到事务初始状态

      redo log重做日志

      在 MySQL 中,如果每一次的更新操作都需要写进磁盘,然后磁盘也要找到对应的那条记录,然后再更新,整个过程 IO 成本、查找成本都很高。为了解决这个问题,MySQL 的设计者就采用了日志(redo log)来提升更新效率。
      而日志和磁盘配合的整个过程,其实就是 MySQL 里的 WAL 技术,WAL 的全称是 Write-Ahead Logging,它的关键点就是先写日志,再写磁盘。
      具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log(redolog buffer)里面,并更新内存(buffer pool),这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候(如系统空闲时),将这个操作记录更新到磁盘里面(刷脏页)。
      Redo log日志相当于笔记本的临时记录功能,每次写数据到数据库不是直接写到数据库,因为可能来不及,先临时记录到Redo log日志中,就标记已经完成了数据的写入操作,只要写入了Redo log,数据早晚会写入到磁盘中。
  • InnoDB自身产生的物理日志,记录数据页的变化

  • InnoDB“日志优先于数据”,记录redo log视为数据已经更新
  • 内存中的数据更新后写redo log,数据被写入硬盘后删除
  • redo log储存在4个1GB文件中,并且循环写入

image.png

  • write pos是当前日志写入点
  • check point是擦除点,数据被更新到硬盘时擦除
    • 物理上4个文件不相连,逻辑上4个文件连在一起。
  • 当write pos追上check point时,事务无法提交,需要等待check point推进。
  • 只要redo log不丢,数据就不会丢失

    数据更新流程

    image.png

    两阶段提交

    MySQL 使用两阶段提交主要解决 binlog 和 redo log 的数据一致性的问题。
    redo log 和 binlog 都可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。下图为 MySQL 二阶段提交简图:
    MySQL日志体系 - 图3
    两阶段提交原理描述:
  1. InnoDB redo log 写盘,InnoDB 事务进入 prepare 状态。
  2. 如果前面 prepare 成功,binlog 写盘,那么再继续将事务日志持久化到 binlog,如果持久化成功,那么 InnoDB 事务则进入 commit 状态(在 redo log 里面写一个 commit 记录)

备注: 每个事务 binlog 的末尾,会记录一个 XID event,标志着事务是否提交成功,也就是说,recovery 过程中,binlog 最后一个 XID event 之后的内容都应该被 purge。

redo log 刷盘参数控制

innodb_flush_log_at_trx_commit参数控制redo log刷盘,默认为1

  • 0:异步每秒刷盘
  • 1:每1个事务刷盘
  • N:每N个事务刷盘

建议设置为1,保证数据安全。

bin log 刷盘参数控制

sync_binlog参数控制binlog刷盘,默认为1

  • 0:自动控制刷盘
  • 1:每1个事务刷盘
  • N:每N个事务刷盘

建议设置为1,保证数据安全

持久化分析

redo log刷盘前系统崩溃:

  • 数据丢失,客户端事务提交不成功会进行重试

redo log刷盘后系统崩溃:

  • 重启时会对redo log进行重放、重写内存中数据页、重写bin log

    为什么redo log写在bin log之前

  • redo log是系统关键节点,相当于“决断点”

  • binlog一旦写入无法撤回,因为可能已经被传送至备库,

如果写在redo log之前,会造成主从数据不一致