前言

MySQL日志主要包括错误日志、查询日志、慢查询日志、事务日志和二进制日志几大类,日志记录着数据库运行期间各种状态信息,本文详细解读MySQL的三大日志:二进制日志(bin log)和事务日志(redo log和undo log)

bin log(归档日志)

binlog用于记录数据库执行的写操作(不含查询),以二进制的形式保存在磁盘中

使用场景

  • .主从复制

在master端开启binlog,然后将binlog发送到各个slave端,slave重放binlog从而达到主从数据一致

  • 数据恢复

通过使用mysqlbinlog工具来恢复数据

刷盘时机

事务执行过程中,会先把日志写到binlog cache,事务提交的时候,再把binlog cache写到binlog文件中;事务提交后的写入只是写入到文件系统的page cache,并没有持久化到磁盘。
刷盘时机通过sync_binlog参数控制,可配置0~N
0:由系统自行判断何时写入磁盘
1:每次commit都将binlog写入磁盘
N:每N个事务,才将binlog写入磁盘

日志格式

STATMENT:基于sql语句的复制(statement-based replication,SBR),每一条修改的sql语句都会记录到binlog中
优点:不需要记录每一行的变化,减少binlog日志量,节约磁盘IO,从而提高性能
缺点:在某些情况下会导致主从数据不一致,如sysdate()、slepp()等
ROW:基于行的复制(row-based-replication,RBR),不记录每条sql语句的上下文信息,仅需记录哪条数据被修改了
优点:不会出现默写特定情况下的存储过程或function/trigger的调用和触发无法被正常复制的问题
缺点:会产生大量的日志,尤其是alter table的时候会让日志暴涨
MIXED:基于STATMENTROW两种模式的混合复制(mixed-based replication,MBR),一般的复制使用statement模式保存binlog,对于statement模式无法复制的操作使用row模式写入binlog

redo log(重做日志)

redolog是InnoDB存储引擎特有的,保证事务持久性的日志

刷盘时机

mysql每执行一条DML语句,先将记录写入内存中的日志缓冲(redo log buffer),后续某个时间点再一次性即将多个操作记录写到磁盘上的日志文件(redo log file),这种先写日志,再写磁盘的技术称为WAL(Write-Ahead Logging)技术
在计算机操作系统中,用户空间(user space)下的缓冲区数据一般情况下是无法直接写入磁盘的,中间必须进过操作系统内核空间(kernel sapce)缓冲区(OS Buffer),因此,redo log buffer写入redo log file实际上是先写入OS Buffer,然后再调用fsync()刷到redo log file中
刷盘时机通过innodb_flush_log_at_trx_commit参数配置:

参数值

含义

缺点

0(延迟写)

每秒将redo log file中日志写入os buffer并调用fsync()写入到redo log file中

当系统崩溃,会丢失一秒钟的数据

1(实时写,实时刷)

事务每次提交都会将redo log buffer中的日志写入os buffer 并调用fsync()刷到redo log file中

因为每次提交都写入磁盘,IO性能较差

2(实时写,延迟刷)

事务每次提交仅写入os buffer,然后每秒调用fsync()将os buffer中的日志刷到redo log file中

扩展

对于MySQL Innodb存储引擎,每次修改后,不仅需要记录redo log还需要记录bin log,而且这两个操作必须保证同时成功/同时失败,否则会造成数据不一致,MySQL采用两阶段提交解决此问题

场景

问题

先写redo log再写bin log

写完redo log,没有写完bin log,主从同步失败,数据不一致

先写bin log再写redo log

写完bin log,写redo log失败,主从同步完毕,主库没有这条数据,数据不一致

写redo log(prepare状态),写bin log,提交事务commit状态

undo log(回滚日志)

undo log作用于事务回滚和多版本并发控制(MVCC),保证事务的原子性

存储方式

在InnoDB存储引擎中,undo log存储在回滚段(Rollback Segment)中,每个回滚段记录了个undo log segment,在每个undo log segment段中进行undo页的申请,在mysql5.6之前,Rollback Segment存储在共享表空间,mysql5.6.3之后,可通过innodb_undo_tablespace设置undo存储的位置

undo的类型

insert undo log

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

update undo log

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

扩展

purge线程两个主要作用是:清理undo页和清除page里面带有Delete_Bit表示的数据行,在InnoDB存在引擎中,事务中的delete操作实际上并不是真正的删除掉数据行,而是通过Delete Mark操作,在记录上标识Delete_Bit,真正的删除通过purge线程完成