redo log也叫做重做日志,它是基于磁盘的数据结构,也有内存中的buffer,他的作用是在崩溃恢复期间用于纠正不完整事务写入的数据。
redo log 主要有两个文件 redo log buffer 和redo log file,前者是内存缓存,易丢失的,后者是磁盘文件,持久化的。redo log是支持覆盖写入的,类似环形链表。这两个文件的默认值大小如下。
在一个事务中的每一次SQL操作之后都会写入一个redo log到buffer中,比如说SQL需要更新张三,李四的的成绩,那么需要查询出来这两条记录加载到内存中,但这两个记录在磁盘中可能在不同的页中,我们知道page页的大小是16KB。但这个更新的数据可能几十字节,如果每一次更新都直接写回磁盘,那么性能可能下降很大。
update set score = 200 where name in ('张三','李四')
如下图,虽然你的SQL是修改张三和李四的成绩,但是MySQL是按照物理页往内存加载的
redo log记录的是InnoDB存储引擎层面的物理页日志,何为物理页日志,就是记录修改了那个表空间,哪个页,修改了什么数据
在事务提交时,然后保证redo log buffer持久到redo log file中,这样就完成了MySQL事务中持久性的特性。
redo log buffer刷盘到redo log file有三种方式,可以通过如下变量配置
1代表的是的事务每次提交都会将log buffer中的日志写入os buffer并调用fsync()刷到log file中,这种方式事务的持久性最好,系统崩溃后恢复时任何数据都不会丢失。
0代表的是事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当MySQL崩溃时,会丢失1秒钟的数据。
2代表的是每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file,这种方式当系统崩溃时会丢失1秒的数据,当MySQL崩溃恢复时不会丢失数据。
innodb_flush_log_at_trx_commit 默认是1,还有0和2
redo log写入磁盘时,是以扇区大小512B写入的,保证每次写都能写入成功,这是一个原子性操作。
要从MySQL服务器崩溃中恢复,唯一的要求是重新启动MySQL服务器。InnoDB 自动检查日志并执行数据库前滚到现在的操作。InnoDB自动回滚崩溃时存在的未提交的事务。
如上图,是更新一条数据的流程,红色的圈中有三个异常点。
异常1发生时,也就是写入redo log失败,这个时候redo和binlog都没有,事务未提交,无任何影响。
异常2发生时,redo log写入成功,binlog写入失败,这个时候MySQL服务器重启后,需要检查binlog是否完整包含此条redo log的更新内容(通过全局事务ID对应),发现binlog中还未包含此事务变更,则丢弃此次变更。
异常3发生时,redo log和binlog都写入成功,但提交事务时MySQL进程崩溃了,那么服务器重启后,检测到redo log和binlog都有,重新提交事务。