MYSQL事务日志

简介

innodb事务日志包括redo log和undo log

  • redo log是重做日志,提供前滚操作
  • undo log是回滚日志,提供回滚操作

redo log

redo log用来记录事务操作引起数据的变化,记录的是数据页的物理修改,用以实现事务的持久性

产生原因

  • 一致性:当我们把数据从内存保存到磁盘的过程中,Mysql是以页为单位进行刷盘的,这里的页并不是磁盘的页,而是Mysql自己的单位,Mysql里的一页数据单位为16K,所以在刷盘的过程中需要把数据刷新到磁盘的多个扇区中去。 而把16K数据刷到磁盘的每个扇区里这个过程是无法保证原子性的,也就意味着Mysql把数据从内存刷到磁盘的过程中,如果数据库宕机,那么就可能会造成一部分数据成功,一部分数据失败的结果。而这个时候通过binlog这种级别的日志是无法恢复的,一个update可能更改了多个磁盘区域的数据,如果根据SQL语句回滚,那么势必会让那些已经刷盘成功的数据造成数据不一致。所以这个时候还是得需要通过redo log这种记录到磁盘数据级别的日志进行数据恢复。
  • 性能:假如每次提交事务之前都先持久化数据,可能会产生大量随机IO影响数据库性能,因此引入redo log将物理修改顺序追加到日志文件中(性能非常高),提交事务后再重做redo log,这就是所谓的预写式技术(Write Ahead logging)
  • 崩溃恢复:当数据库系统崩溃时,虽然数据没有持久化,但是Redo log已经持久化了。在系统从崩溃中恢复时,可以根据Redo log中的内容,将所有的数据恢复到最新的状态。

日志文件持久化策略

image.png

MySQL支持用户自定义在commit时如何将log buffer中的日志刷log file中。
这种控制通过变量 innodb_flush_log_at_trx_commit 的值来决定。
该变量有3种值:0、1、2,默认为1

  • 当设置为0的时候,事务提交时就不会将log buffer中的日志写入os buffer,而是每秒写入os buffer并调用fsync将数据刷新到磁盘上,可能会丢失一秒的数据
  • 当设置为1的时候,事务每次提交都会将log buffer中的日志写入os buffer并调用fsync刷到log file on disk中。这种方式即使系统崩溃也不会丢失任何数据,但是因为每次提交都会进行一次IO操作,IO性能较差,频繁调用IO太影响性能。
  • 当设置为2的时候,每次提交都仅写入到os buffer,然后是每秒调用fsync()将os buffer中的日志写入到磁盘,当系统崩溃时,数据也只写入了os buffer也可能会丢失,但比0好一些。

注意:当设置为0或2的时候秒级调用fsync()将数据写入磁盘,这时批量操作,而设置为1是,是每次数据修改都将数据写入磁盘,是单次操作。

redo log和bin log一致性

binlog和redo log必须保持一致,不允许出现binlog有记录但redolog没有的情况,反之亦然。在一个事务中,redolog有prepare和commit两种状态,所以,在redolog状态为prepare时记录binlog可保证两日志的记录一致,下图列出各种情况来说明。


image.png

redo log和bin log区别

  • 功能不同,binlog主要用于归档主从复制,而redo log主要用于崩溃恢复
  • 内容不同,binlog是逻辑日志,而redo log是物理日志
  • 写入时机不同,binlog是server层记录的,所有存储引擎可共享,而redo log是InnoDB引擎特有的
  • 写入方式不同,binlog容量无限,追加写入,而redo log容量有限,循环写入

undo log

undo log有两个作用:提供回滚和多个行版本控制(MVCC)

在数据修改的时候,不仅记录了redo,还记录了相对应的undo,如果因为某些原因导致事务失败或回滚了,可以借助该undo进行回滚。
undo log和redo log记录物理日志不一样,它是逻辑日志。可以认为当delete一条记录时,undo log中会记录一条对应的insert记录,反之亦然,当update一条记录时,它记录一条对应相反的update记录。
当执行rollback时,就可以从undo log中的逻辑记录读取到相应的内容并进行回滚。
应用到行版本控制的时候,也是通过undo log来实现的:当读取的某一行被其他事务锁定时,它可以从undo log中分析出该行记录以前的数据是什么,从而提供该行版本信息,让用户实现非锁定一致性读取。
undo log是采用段(segment)的方式来记录的,每个undo操作在记录的时候占用一个undo log segment。
另外,undo log也会产生redo log,因为undo log也要实现持久性保护

你可能感兴趣的:(MYSQL事务日志)