redo log(重做日志) 确保事务的持久性
redo log 是存储引擎层生成的日志,记录的是物理级别上的页修改操作,比如页号、偏移量、写入的数据。主要保证数据的可靠性
redo log 日志的好处
- redo日志降低了刷盘频率
- redo日志占用的空间非常小
存储表空间ID、页号、偏移量以及需要更新的值,所需的存储空间是很小的,刷盘快。
redo log 日志的特点
redo日志是顺序写入磁盘的
在执行事务的过程中,每执行一条语句,就可能产生若干条redo日志,这些日志是按照产生的顺序写入磁盘的,也就是使用顺序IO,效率比随机快。
事务执行过程中,redo日子不断记录
redo日志跟bin日志的区别,redo日志是存储引擎产生的,bin日志是数据库层产生的,假设一个事务,对表做了10万行的记录插入,这个过程中,一直不断的网redo日志顺序记录,而bin日志不记录,知道这个事务提交,才会一次性写入bin日志文件中
redo的组成
重做日志的缓冲
保存在内存中,易丢失。在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间,即redo日志缓冲区,这片内存空间被划分成若干连续的redo log block。一个redo log block 占用512字节大小。
重做日志文件
保存在硬盘,是持久的。
redo的整体提流程
- 先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
- 生成一条重做日志并写入redo log buffer,记录的是数据被修改后的值
- 当事务commit时,将redo log buffer中的内容刷新到 redo log file,对redo log file 采用追加写的方式
- 定期将内存中的修改的数据刷新到磁盘中
redo日志的刷盘策略
redo日志的写入并不是直接写入磁盘,InnoDB引擎在写redo日志的时候先写redo log buffer,之后以一定的频率刷入到真正的redo log file中。
注意:redo log buffer刷盘到redo log file的过程并不是真正的刷到磁盘中区,只是刷入到文件系统缓存(page cache)中去,真正的写入会交给系统自己决定。那么对于InnoDB来说就存在一个问题,如果交给系统来同步,童谣如果系统宕机,那么数据也丢失了。
针对这种情况,InnoDB给出innodb_flush_log_at_trx_commit参数,该参数控制commit提交事务时,如何将redo log buffer中的日志刷新到redo log file中。三种策略:
- 设置为0:表示每次事务提交时不进行刷盘操作(系统默认master thread每隔1s进行一次重做日志的同步)
- 设置为1:表示每次事务提交时都将进行同步,刷盘操作(默认值)
- 设置为2:表示每次事务提交时都只把redo log buffer 内容写入page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。
undo log(回滚日志) 保证事务的原子性、一致性
undo log 是存储引擎层生成的日志.,记录的 是逻辑操作日志,比如对某一行数据进行了insert语句操作,那么undo log就记录一条阈值相反的delete操作,主要用于事务的回滚和一致性非锁定读。
undo日志的作用
回滚数据
MVCC
在InnoDB存储引擎中MVCC的实现是通过undo来完成的,当用户读取一行记录时,若该记录已经被其他事务占用,当前事务可以通过undo读取之前的版本行信息,以此实现非锁定读。
undo的存储结构
回滚段与undo页
InnoDB对undo日志的管理采取段的方式,即回滚段,每个回滚段记录了1024个undo log segment,而在每个undo log segment段中进行undo页的申请。
- 在InnoDB1.1版本之前,只有一个rollback segment,因此支持同时在线的事务限制为1024,虽然对绝大多数的应用来说都已经够用。
- 从1.1版本开始InnoDB支持最大128个rollback segment,故其支持同时在先的事务限制提高了128*1024.
show variables like 'innodb_undo_logs'
- innodb_undo_directory:设置rollback segment文件所在的路径,这意味着rollback segment可以存放在共享表空间意外的位置,即可以设置为独立表空间。该参数的默认值为'./',表示当前InnoDB存储引擎的目录。
- innodb_undo_logs:设置rollback segment的个数,默认128.
- innodb_undo_tablespaces:设置构成rollback segment文件的数量,这样rollback segment可以较为平均的分布在文件中,设置该参数后,会在路径innodb_undo_directory看到undo为前缀的文件,该文件就会代表rollback segment文件。
undo页的重用
当我们开启一个事务需要写undo日志的时候,就得先去undo log segment中去找到一个空间的位置,当有空位的时候,就去申请undo页,在这个申请到的undo页中进行undo log的写入,我们知道mysql默认一页的大小时16k。
为每一个事务分配一个页,时非常浪费的,假设你的应用的TPS(每秒处理事务数目)为1000,那么1s就需要1000页,大概需要16M的存储,1分钟大概1G,很多空间浪费。
于是undo页就被设计的可以重用了,当食物提交时,并不会立刻删除undo页。因为重用,所以这个undo页可能混杂这其他事务 的undo log,undo log 在commit后,会 被放到一个链表中,然后判断undo页的使用空间是否小于3/4,如果小于3/4的话,则表示当前的undo页可以被重用,那么他就不会被回收,其他事务的undo log可以记录在但钱undo页的后面,由于undo log是离散的,所以清理对应的磁盘空间时,效率不高。
回滚段与事务
- 每个事务只会使用一个回滚段,一个回滚段在同一时刻可能会服务于多个事务
- 每一个事务开始的时候,会制定一个回滚段,在事务进行的过程中,当数据被修改时,原始的数据会被复制到回滚段。
- 在回滚段中,事务会不断填充盘区,知道事务结束或所有的空间被用完,如果但钱的盘区不够用,事务会在段中请求扩展一下盘区,如果所有已分配的盘区都被用完,事务会覆盖最初的盘区或者 在回滚段允许的情况下扩展新的盘区来使用。
- 回滚段存在于undo表空间中,在数据库中可以存在多个undo表空间,但同一时刻只能使用一个undo表空间。
- 事务提交时,InnoDB存储引擎会做一下两件事情
- 将undo log放入列表中,以供之后的purge操作
- 判断undo log所在的页是否可以重用,若可以分配给下个事务使用。