不同于binlog是MySQL Server层的日志,Redo log是InnoDB引擎特有的日志。Redo log文件是InnoDB用于崩溃恢复(crash recovery)以及组提交(group commit)策略的重要文件,存在于磁盘上。下面大致讲解下Redo log是怎么做到崩溃恢复以及组提交的。
崩溃恢复能力是指InnoDB可以保证数据库在异常崩溃重启后的状态和使用binlog文件恢复出来的数据库状态保持一致。
我们可以假设没有redo log,只有binlog,那么数据文件更新和写入binlog的顺序有两种可能:
第一种情况如果在完成步骤1后服务器异常关闭,则导致binlog中缺少最后更新的数据;第二种情况如果在完成步骤1后服务器异常关闭,则数据库中比binlog中少了最后的数据变更记录。此时如果使用binlog文件进行恢复数据库(比如备库),则会导致数据库不一致的情况。
先上一张图,是InnoDB更新数据时update语句的执行流程(摘自极客时间《MySQL实战45讲》,自己重新绘制),橙色的流程在InnoDB内部执行,蓝色的部分在MySQL Server层的执行器中执行。图片以下条sql语句为例。
update T set c=c+1 where ID=2;
如上图所示,redo log的写入分为两个阶段(prepare和commit),这个称作两阶段提交,保证了数据的正确性。下面我们从上图4个可能发生异常关闭的时间点来分析InnoDB如何在MySQL启动时做崩溃恢复。
如果服务器异常关闭发生在Point A以及之前的时间点,这个时候redolog 和 binlog都没有任何记录,事务还未提交,不会造成任何影响。
当服务器启动的时候发现redo log里处于prepare状态的记录,这个时候需要检查binlog是否完整包含此条redo log的更新内容(通过全局事务ID对应),发现binlog中还未包含此事务变更,则丢弃此次变更。
和Point B基本相同,只不过此时发现binlog中包含redo log的更新内容,此时事务会进行提交。
binlog中和数据库中均含有此事务的变更,没有任何影响。
上面关于崩溃恢复部分只是讲了写redo log和binlog的步骤,那么一定很疑惑数据是何时被写入到磁盘文件中的呢,这里就要说下InnoDB通过redo log实现的组提交的策略了。
因为更新数据时写磁盘的操作是随机写,这部分的IO消耗很大,而通过组提交(多个事务的变更统一写磁盘)的方式可以提升系统的吞吐量。
默认是两个文件,存在datadir目录中,文件名分别为ib_logfile0
和ib_logfile1
。datadir可以通过命令select @@datadir;
查看:
mysql> select @@datadir;
+---------------------------------------+
| @@datadir |
+---------------------------------------+
| c:\wamp64\bin\mysql\mysql5.7.21\data\ |
+---------------------------------------+
文件数量和每个文件的大小可以通过变量innodb_log_files_in_group
和innodb_log_file_size
来设置,这两个变量都是只读变量,只能通过在配置文件中修改并重启的方式生效。redo log文件的总大小(innodb_log_file_size * innodb_log_files_in_group)一般建议配置为可以处理一个小时写操作的量,数值越大则通过checkpoint刷新的次数越少,就越能降低磁盘IO。
配置文件(my.cnf/my.ini):
[mysqld]
innodb_log_files_in_group=4
innodb_log_file_size=1073741824
查看变量:
mysql> show variables like 'innodb_log_file%';
+---------------------------+------------+
| Variable_name | Value |
+---------------------------+------------+
| innodb_log_file_size | 1073741824 |
| innodb_log_files_in_group | 4 |
+---------------------------+------------+
查看磁盘文件:
C:\wamp64\bin\mysql\mysql5.7.21\data
λ ls -alh | grep ib_log
-rw-r--r-- 1 username 1049089 1.0G Apr 24 10:45 ib_logfile0
-rw-r--r-- 1 username 1049089 1.0G Apr 24 10:44 ib_logfile1
-rw-r--r-- 1 username 1049089 1.0G Apr 24 10:44 ib_logfile2
-rw-r--r-- 1 username 1049089 1.0G Apr 24 10:45 ib_logfile3
如下图是一组redo log文件的工作的示意图(摘自极客时间《MySQL实战45讲》,自己重新绘制)
如图中所示,一组redo log文件是一个类似环形的状态,循环利用。
write pos指的是当前写入redo log的位置,check point是要擦除并更新到数据文件的位置,所以write pos 到check point 位置就是还未使用的空闲空间。
感兴趣的推荐订阅丁奇大神的专栏《MySQL实战45讲》,感觉是最负责的一个专栏作者,好多篇作者回复评论都有上百条,真心推荐超值。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。