参考:https://blog.csdn.net/luokn1995/article/details/108371825

binlog

概述

记录数据库执行的写入操作信息,以二进制的形式保存在磁盘中。binlog是mysql的逻辑日志,并且由Server曾进行记录,使用任何存储引擎的mysql数据库都会记录binlog日志。

使用场景

  1. 主从复制:在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端更新数据;
  2. 数据恢复:通过mysqlbinlog工具恢复数据。

刷盘时机

mysql通过sync_binlog参数控制binlog的刷盘时机,取值范围是0-N:

  • 0:不去强制要求,由系统自行判断何时写入磁盘;
  • 1:每次commit的时候都要将binlog写入磁盘;
  • N:每N个事务,才会将binlog写入磁盘。

日志格式

binlog日志有三种格式,分别为STATEMENT、ROW和MIXED。

  • STATEMENT:基于SQL语句的复制,每一条会修改数据的SQL语句会记录到binlog中。
    • 优点:不需要记录每一行的变化,减少了binlog的日志量,节约了IO从而提高了性能
    • 缺点:在某些情况下会导致主从数据不一致,比如执行sysdate()、sleep()
  • ROW:基于行的复制,不记录每条SQL语句的上下文信息,仅需记录哪条数据被修改了。
    • 优点:不会出现某些特定情况下的存储过程、或function、或trigger的调用和触发无法被正确复制的问题
    • 缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨
  • MIXED:基于STATEMENT和ROW两种模式的混合复制,一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog

redo log

基本概念

redo log包括两部分:

  1. redo log buffer(内存中的日志缓冲),易失的
  2. redo log file(磁盘上的日志文件),持久的

记录过程

mysql每执行一条sql语句,先将记录写入redo log buffer,后续某个时间点再一次性将多个操作记录写到redo nlog file,这种先写日志,再写磁盘的技术就是WAL(Write-AHead logging,预写式日志)技术。

在OS中,用户空间(user space)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核空间(kernel space)缓冲区(OS Buffer)。因此,redo log buffer下入redo log file实际上是先写入OS Buffer,然后再通过系统调用fsync()将其刷到redo log file中。

写入场景

  • 数据页修改完成,脏页刷出磁盘,记录redo log
  • 聚集索引、二级索引、undo页面的修改,记录redo log

写入时机

mysql支持三种将redo log buffer写入redo log file的时机,可以通过innodb_flush_log_at_trx_commit参数配置:

参数值 含义
0(延迟写) 事务提交不会将redo log buffer中日志写入到OS Buffer,而是每秒写入OS Buffer并调用fsync()写入到redo log file中。也就是说设置为0时是每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。
1(实时写,实时刷) 事务每次提交都会将redo log buffer中的日志写入到OS Buffer并调用fsync刷到redo log file中,这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO性能较差。
2(实时写,延迟刷) 事务每次提交都仅写入到OS Buffer,然后是每秒调用fsync()将OS Buffer中的日志写入到redo log file。

undo log

基本概念

undo log有两个作用:

  • 回滚
  • MVCC

写入时机

  • DML操作修改聚簇索引前,记录undo log
  • undo log页面的修改,记录undo log

日志类型

  • insert undo log
  • update undo log

insert undo log是指在insert操作中产生的undo log,因为insert操作的记录,只对事务本身可见,对其他事务不可见。该undo log可以在事务提交后直接删除,不需要进行purge操作。

update undo log记录的是对delete和update操作产生的undo log,该undo log可能需要提供MVCC机制,因此不能在事务提交时就进行删除。提交时放入undo log链表,等待purge线程进行最后的删除。

:::info purge线程的作用:清理undo页和清除page里面带有Delete_Bit标识的数据行。
在InnoDB中,事务中的Delete操作不会物理删除,而是标识操作即逻辑删除。 :::

demo

  1. 假设有AB两个数据,值分为12
  2. 1. 事务开始
  3. 2. 记录A=1undo log
  4. 3. 修改A=3
  5. 4. 记录A=3redo log
  6. 5. 记录B=2undo log
  7. 6. 修改B=4
  8. 7. 记录B=4redo log
  9. 8. redo log写入磁盘
  10. 9. 事务提交

在InnoDB内存中,一般顺序如下:

  1. 写undo的redo
  2. 写undo
  3. 修改数据页
  4. 写redo