redo log是InnoDB存储引擎层的日志,又称重做日志文件,
用于记录事务操作的变化,记录的是数据修改之后的值,不管事
务是否提交都会记录下来。一个事务生成的redo日志是按顺序写
入磁盘的,是顺序IO,在实例和介质失败(media failure)
时,redo log文件就能派上用场,如数据库掉电,InnoDB存储
引擎会使用redo log恢复到掉电前的时刻,以此来保证数据的
完整性。
redo log包括两部分:一个是内存中的日志缓冲
(redo log buffer),另一个是磁盘上的日志文件
(redo log file)。mysql每执行一条DML语句,先将
记录写入redo log buffer,后续某个时间点再一次性
将多个操作记录写到redo log file。这种先写日志,再
写磁盘的技术就是MySQL里经常说到的WAL
(Write-Ahead Logging) 技术。
2、redo log记录形式
redo log日志的大小是固定的,即记录满了以后就从头循环写。
2.1 redolog记录方式:
简单的redo日志:
记录哪个表空间中的哪个页面从哪个位置
开始的多少个节点要修改成什么
复杂的redo日志:
记录了对哪个表空间的哪个页面进行修改,存储了对该页面进行
修改操作的一些必备要素,重启时,MySQL会根据redo日志的类
型,将redo日志中的必备要素作为参数,调用日志类型对应的函
数,恢复数据
3、redo log buffer刷盘的过程
在计算机操作系统中,用户空间(user space)下的缓冲区数据
一般情况下是无法直接写入磁盘的,中间必须经过操作系统内核
空间(kernel space)缓冲区(OS Buffer)。因此,redo log
buffer写入redo log file实际上是先写入OS Buffer,然后再
通过系统调用fsync()将其刷到redo log file中
4、redo log buffer刷盘时机
redo log buffer只是用户空间中的一块内存区域,如何让这块
区域中的数据能持久化到磁盘即redo log file中,什么时候
刷盘?
MySQL提供了参数: innodb_flush_log_at_trx_commit
| 参数值 | 说明 |
|---|---|
| 0 | 每秒写一次日志并将其刷新到磁盘 |
| 1 | 推荐值:表示当你commit时,MySQL必须将rodolog-buffer中的数据刷新进磁盘中。确保只要commit是成功的, 磁盘上就得有对应的rodolog日志。这也是最安全的情况。 |
| 2 | 表示当你commit时,将redolog-buffer中的数据刷新进OS Cache中,然后依托于操作系统每秒刷新一次的机制 将数据同步到磁盘中,也存在丢失的风险。 |
双1设置
始终设置 innodb_flush_log_at_trx_commit=1 如果启用了二进制日志记录,请设置 sync_binlog=1。
前者保证redolog的不丢失、后者保证了binlog的不丢失
5、redo log组成
redo log可以大致分为两个部分
重做日志的缓存(redo log buffer)
其特点为保存在内存中,容易丢失。
在服务器启动时就向操作系统申请了一大片称之为••redo log buffer••
的连续内存空间,翻译成中文就是redo日志缓冲区。这片内存空间被
划分成若十个连续的 ••redo log block••。一个••redo log block••
占用512字节大小。


redo log buffer配置:
show variables like '%innodb_log_buffer_size%';
redo log buffer默认大小是16MB,最大值4096MB,最小1MB
重做日志文件(rodo log file)
特点:保存在硬盘中,保证持久性
可以在MySQL 的data数据目录中找到如下文件,••ib_logfile0•
•和••ib_logfile1••就是Redo日志文件
redo log group:
redo log group说的是:由N个大小相同的redo log组成一
个redo log group。N的值默认为2。
默认单个redo log文件的大小是48MB,可以通过参数:
innndb_log_files_size 进行修改
日志文件的总大小:
(innodb_log_file_size* innodb_log_files_in_group)
不能超过略小于512GB的最大值
以上参数可以通过如下指令查看:
show global variables like 'innodb_log%';


innodb将log buffer中的redo log block刷新到logfile中时,
以追加的方式循环写入。也就是首先在ib_logfile0的尾部追加,
写满后再写ib_logfile1。当ib_logfile1写满时,清空一部分
ib_logfile0接着追加写
redo log file的大小对innodb性能影响非常大。通常来说要设
置的足够大,大到可以让MySQL支持1小时线上高峰流量的接入而
不切换。但是设置的过大,数据恢复的时间比较长。设置过小导
致循环切换redo log file。
二、bin log(二进制日志)
2.1 基本概念
binlog是属于MySQL Server层面的,又称为归档日志,
属于逻辑日志,是以二进制的形式记录的,用于记录数据
库执行的写入性操作(不包括查询)信息,依靠binlog是没
有crash-safe能力的
所谓crash-safe能力指的是,mysql事务在运行过程中,
突然发生崩溃,然后重启服务器后能保证事务的完整性。
binlog是通过追加的方式进行写入的,可以通过
max_binlog_size参数设置每个binlog文件的大小,
当文件大小达到给定值之后,会生成新的文件来保存日志。
逻辑日志和物理日志: 逻辑日志:可以简单理解为记录的就是sql语句 物理日志:因为mysql数据最终是保存在数据页中的,物理日志记录的就是数据页变更
2.2 应用场景
在实际应用中,binlog的主要使用场景有两个
主从复制:在Master端开启binlog,然后将binlog发送到各个Slave端,Slave端重放binlog从而达到主从数据一致
数据恢复:通过使用mysqlbinlog工具来恢复数据。
2.3 binlog日志格式
binlog日志有三种格式,分别为STATMENT、ROW和MIXED MySQL 5.7.7之前,默认的格式是STATEMENT 之后,默认值是ROW 日志格式通过binlog-format指定。
STATMENT 基于SQL语句的复制(statement-based replication, SBR) ,每一条会修改数据的sql语句会记录到binlog中
| 优点 | 缺点 |
|---|---|
| 不需要记录每一行的变化,减少了binlog 日志量,节约了IO, 从而提高了性能 | 在某些情况下会导致主从数据不一致, 比如执行sysdate()、sleep()等 |
ROW 基于行的复制(row-based replication, RBR),不 记录每条sql语句的上下文信息,仅需记录哪条数据被修改了
| 优点 | 缺点 |
|---|---|
| 不会出现某些特定情况下的存储过程、 或function、或trigger的调用和触发无法被正确复制的问题 | 会产生大量的日志,尤其是alter table的时候会让日志暴涨 |
MIXED 基于STATMENT和ROW两种模式的混合复制(mixed-based replication, MBR),一般的复制使用STATEMENT模式保存binlog,对于STATEMENT模式无法复制的操作使用ROW模式保存binlog
2.4 redolog与binlog区别
redo log是属于innoDB层面,binlog属于MySQL Server层面 的,这样在数据库用别的存储引擎时可以达到一致性的要求。
redo log是物理日志,记录该数据页更新的内容;binlog是逻 辑日志,记录的是这个更新语句的原始逻辑
redo log是循环写,日志空间大小固定;binlog是追加写,是 指一份写到一定大小的时候会更换下一个文件,不会覆盖。
binlog可以作为恢复数据使用,主从复制搭建,redo log作为 异常宕机或者介质故障后的数据恢复使用。
redo log是InnoDB存储引擎层的日志,binlog是MySQL Server 层记录的日志, 两者都是记录了某些操作的日志(不是所有)自然 有些重复(但两者记录的格式不同)。
三、undo log
3.1 定义
数据库事务四大特性中有一个是原子性,具体来说就是 原
子性是指对数据库的一系列操作,要么全部成功,要么全部
失败,不可能出现部分成功的情况。
redo log是事务持久性的保证,undo log是事务原子
性的保证。在事务中更新数据的前置操作其实是要先写入一个
undo log。
3.2 应用场景
用于数据的回滚。比如数据执行时候发生错误,操作系统的错误,断点等,程序员手动rollback等操作场景都会用到数据的回滚。
实现MVCC。即在InnoDB存储引擎中MVCC的实现是通过undo来完成。当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的行版本信息,以此实现非锁定读取。
3.3 日志细节
对记录完成写操作时(INSERT,UPDATE,DELETE),都需要
把数据回滚时用的东西记录下来。
插入一条记录时,至少要把这条记录的主键值记下来,之后回滚的时候只需要把这个主键值对应的记录删掉就好了。(对于每个INSERT, InnoDB存储引擎会完成一个DELETE)
删除了一条记录,至少要把这条记录中的内容都记下来,这样之后回滚时再把由这些内容组成的记录插入到表中就好了。(对于每个DELETE,InnoDB存储引擎会执行一个INSERT)
修改了一条记录,至少要把修改这条记录前的旧值都记录下来,这样之后回滚时再把这条记录更新为旧值就好了。(对于每个UPDATE,InnoDB存储引擎会执行一个相反的UPDATE,将修改前的行放回去)
四、总结
