什么是redo log?redo log称为重做日志,用于记录对数据页做了什么修改(而不是记录修改后的数据页状态),通常是物理日志,用来恢复提交后的物理数据页。
打个比方,redo log类似饭馆赊账的小黑板,而磁盘相当于账本。当有人赊账时,可以先写到小黑板,然后等打烊了以后再更新到账本。这种小黑板和账本配合的方式就是WAL(Write-Ahead Logging),关键在于先写日志,再写磁盘,这样可以提高效率。redo log的容量是固定的,写到末尾就要回到开头循环写,假设配置了一组4个文件,每个文件大小1G,则redo log的容量为4G,如下图:
write pos是当前日志的位置,边写边后移,写到file-3末尾就要回到file-0;check point是当前要檫除的位置,檫除前要将数据更新到磁盘。而write pos和check point之间的空间就是redo log剩余可用的空间。如果 write pos 追上 checkpoint,表示"小黑板"满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。
有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为 crash-safe。
redo log包括两部分:一是内存中的日志缓冲(redo log buffer),该部分日志是易失性的;二是磁盘上的重做日志文件(redo log file),该部分日志是持久的。
在概念上,InnoDB通过force log at commit机制实现事务的持久性,即在事务提交的时候,必须先将该事务的所有事务日志写入到磁盘上的redo log file和undo log file中进行持久化。
为了确保每次日志都能写入到事务日志文件中,在每次将log buffer中的日志写入日志文件的过程中都会调用一次操作系统的fsync操作(即fsync()系统调用)。因为MariaDB/MySQL是工作在用户空间的,MariaDB/MySQL的log buffer处于用户空间的内存中。要写入到磁盘上的log file中(redo:ib_logfileN文件,undo:share tablespace或.ibd文件),中间还要经过操作系统内核空间的os buffer,调用fsync()的作用就是将OS buffer中的日志刷到磁盘上的log file中。
也就是说,从redo log buffer写日志到磁盘的redo log file中,过程如下:
当设置为1的时候,事务每次提交前都会将log buffer中的日志写入os buffer并调用fsync()刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都写入磁盘,IO的性能较差。(建议设置为1) 当设置为0的时候,事务提交时不会将log buffer中日志写入到os buffer,而是每秒写入os buffer并调用fsync()写入到log file on disk中。也就是说设置为0时是(大约)每秒刷新写入到磁盘中的,当系统崩溃,会丢失1秒钟的数据。 当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到log file on disk。
设置为0和2的异同:
为0时,事务提交只写log buffer,为2时,事务提交只写os buffer,1秒后都刷写磁盘;如果服务器发生宕机,两者都丢失1秒数据;而如果只是MySQL服务挂掉,为0时会丢失1秒数据,为2时由于写了os buffer,不会丢失数据。
什么是undo log?undo log叫做回滚日志,用于记录数据被修改前的信息。undo log主要记录的是数据的逻辑变化,为了在发生错误时回滚之前的操作,需要将之前的操作都记录下来,然后在发生错误时才可以回滚。
