MySQL系列之redolog、undolog和binlog详解
事务的实现
redo log保证事务的持久性,undo log⽤来帮助事务回滚及MVCC的功能。
InnoDB存储引擎体系结构
redo log
Write Ahead Log策略
事务提交时,先写重做⽇志再修改页;当由于发⽣宕机⽽导致数据丢失时,就可以通过重做⽇志来完成数据的恢复。
InnoDB⾸先将重做⽇志信息先放到重做⽇志缓存
按⼀定频率刷新到重做⽇志⽂件mysql下载的zip版本安装步骤
重做⽇志⽂件:在默认情况,InnoDB存储引擎的数据⽬录下会有两个名为ib_logfile1和ib_logfile2的⽂件。每个InnoDB存储引擎⾄少有1个重做⽇志⽂件组(group),每个⽂件组下⾄少有2个重做⽇志⽂件。
下⾯图⼀,很好说明重做⽇志组以循环写⼊⽅式运⾏,InnoDB存储引擎先写ib_logfile1,当达到⽂件最后时,会切换⾄重做⽇志⽂件ib_logfile2.
⽽图2,增加⼀个OS Buffer,有助于理解fsync过程。
关于log group,称为重做⽇志组,是⼀个逻辑上的概念。InnoDB存储引擎实际只有⼀个log group。
log group中第⼀个redo log file,其前2KB部分保存4个512字节⼤⼩块:
重做⽇志缓冲刷新到磁盘
下⾯三种情况刷新:
Master Thread每⼀秒将重做⽇志缓冲刷新到重做⽇志⽂件
每个事务提交时会将重做⽇志缓冲刷新到重做⽇志⽂件
当重做⽇志缓冲池剩余空间⼩于1/2时,重做⽇志刷新到重做⽇志⽂件
补充上述三种情况第⼆种,触发写磁盘过程由参数innodb_flush_log_at_trx_commit控制,表⽰提交(commit)操作时,处理重做⽇志的⽅式。
参数innodb_flush_log_at_trx_commit有效值有0、1、2
0表⽰当提交事务时,并不将事务的重做⽇志写⼊磁盘上⽇志⽂件,⽽是等待主线程每秒刷新。
1表⽰在执⾏commit时将重做⽇志缓冲同步写到磁盘,即伴有fsync的调⽤
2表⽰将重做⽇志异步写到磁盘,即写到⽂件系统的缓存中。不保证commit时肯定会写⼊重做⽇志⽂件。
0,当数据库发⽣宕机时,部分⽇志未刷新到磁盘,因此会丢失最后⼀段时间的事务。
2,当操作系统宕机时,重启数据库后会丢失未从⽂件系统缓存刷新到重做⽇志⽂件那部分事务。
下图有助于理解
重做⽇志块
在InnoDB存储引擎中,重做⽇志都是以512字节进⾏存储的。意味着重做⽇志缓存、重做⽇志⽂件都是以块(block)的⽅式进⾏保存的,每块512字节。重做⽇志头12字节,重做⽇志尾8字节,故每个重做⽇志块实际可以存储492字节。
重做⽇志格式
redo log是基于页的格式来记录的。默认情况下,innodb的页⼤⼩是16KB(由 innodb_page_size变量控制),⼀个页内可以存放⾮常多的log block(每个512字节),⽽log block中记录的⼜是数据页的变化。log body的格式分为4部分:
redo_log_type:占⽤1个字节,表⽰redo log的⽇志类型。
space:表⽰表空间的ID,采⽤压缩的⽅式后,占⽤的空间可能⼩于4字节。
page_no:表⽰页的偏移量,同样是压缩过的。
redo_log_body表⽰每个重做⽇志的数据部分,恢复时会调⽤相应的函数进⾏解析。例如insert语句和delete语句写⼊redo log的内容是不⼀样的。
如下图,分别是insert和delete⼤致的记录⽅式。
redo⽇志恢复
下⾯LSN(Log Sequence Number)代表checkpoint,当数据库在LSN为10000时发⽣宕机,恢复操作仅
恢复LSN10000-LSN13000范围内⽇志
undo log
undo log的作⽤
undo是逻辑⽇志,只是将数据库逻辑地恢复到原来的样⼦;所有修改都被逻辑地取消了,但是数据结构和页本⾝在回滚之后可能不⼤相同。
undo log有两个作⽤:提供回滚和多个⾏版本控制(MVCC)。
InnoDB存储引擎回滚时,对于每个INSERT,会完成⼀个DELETE;对于每个DELETE,会执⾏⼀个INSERT;对于每个UPDATE,会执⾏⼀个相反的UPDATE,将修改前的⾏放回去。MVCC:当⽤户读取⼀⾏记录时,若该记录已经被其他事务占⽤,当前事务可以通过undo读取之前的⾏版本信息,以此实现⾮锁定读取。
undo log的存储⽅式
innodb存储引擎对undo的管理采⽤段的⽅式。rollback segment称为回滚段,每个回滚段中有1024个undo log segment。
在以前⽼版本,只⽀持1个rollback segment,这样就只能记录1024个undo log segment。后来MySQL5.5可以⽀持128个rollback segment,即⽀持128*1024个undo操作,还可以通过变量innodb_undo_logs (5.6版本以前该变量是 innodb_rollback_segments )⾃定义多少个rollback segment,默认值为128。
undo log默认存放在共享表空间中。
事务提交undo log处理过程
当事务提交时,InnoDB存储引擎会做以下两件事:
将undo log放⼊⼀个列表中,以供之后的purge使⽤,是否可以最终删除undo log及所在页由purge线程来判断
判断undo log 所在的页是否可以重⽤,若可以,分配给下个事务使⽤
当事务提交时,⾸先将undo log放⼊链表中,然后判断undo页的使⽤空间是否⼩于3/4,若是,则表⽰该undo页可以被重⽤,之后新的undo log记录在当前undo log的后⾯
undo log分为:
insert undo log
update undo log
因为事务隔离性,insert undo log对其他事务不可见,所以该undo log可以在事务提交后直接删除,不需要进⾏purge操作。
update undo log记录的是对delete和update操作产⽣的undo log。该undo log可能需要提供MVCC机制,因此不能提交时就进⾏删除
update分为两种情况:
date的列如果不是主键列,在undo log中直接反向记录是如何update的。即update是直接进⾏的。
update主键的操作可以分为两步:
⾸先将原主键记录标记为已删除,因此需要产⽣⼀个类型为TRX_UNDO_DEL_MARK_REC的undo log
之后插⼊⼀条新的记录,产⽣⼀个类型为TRX_UNDO_INSERT_MARK_REC的undo log
InnoDB purge时,会先从history列表undo log,然后再从undo page中undo log;可以避免⼤量随机读取操作,从⽽提⾼purge效率。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论