1. redo log
1.1 redo log含义
- 它是物理日志。本质上记录的是对某个表空间的某个数据页的某个偏移量的地方修改了几个字节的值。
- 记录的内容:表空间号+数据页号+偏移量+修改几个字节的值+具体的值
1.2 redo log类型
类型 | 含义 |
MLOG_1BYTE | 表示这条日志只修改了1字节的值 |
MLOG_2BYTE | 表示这条日志只修改了2字节的值 |
MLOG_4BYTE | 表示这条日志只修改了4字节的值 |
MLOG_8BYTE | 表示这条日志只修改了8字节的值 |
MLOG_WRITE_STRING | 表示在某个数据页的某个偏移量的位置插入或修改了一大串的值 |
1.3 redo log结构
- 对于日志类型不是MLOG_WRITE_STRING的类型的结构如下
- 日志类型,表空间id,数据页号,数据页中的偏移量,具体修改的数据
- 对于日志类型是MLOG_WRITE_STRING的类型的结构如下
- 日志类型,表空间id,数据页号,数据页中的偏移量,修改数据长度,具体修改的数据
1.4 redo log block
- 其实我们的redo log日志记录会先放入redo log block这个数据结构中,然后再将redo log block写入redo log磁盘物理文件中的。
- 一个redo log block可以存多条redo log记录
- redo log block大小为512字节
- redo log buffer是内存申请的一片连续内存,里面划分出了N个redo log block空间。
1.5 redo log block的结构
结构名称 | 字段 | 作用 |
header块头(12字节) | block no(4字节) | block块的唯一编号 |
data length(2字节) | 向body中写入了多少字节数 | |
first record group(2字节) | 每个事务可能会有多个redo log,一个事务里的redo log属于一个redo log group。这个字段记录的是在这个block中的第一组redo log 的偏移量。 | |
checkpoint no(4字节) | 检查点保存了日志序列号 | |
body块(496字节) | 存放redo log | |
trailer尾块(4字节) |
- 我们在执行一个事务的过程中,每个事务可能会有多个增删改操作,那么就会有多个redo log,这多个redo log就是一组redo log,每次一组redo log都是先在别的地方暂存,然后当执行完,在把这一组的redo log 按顺序写入到redo log buffer里的block里去。
- 如果一组的redo log实在太多,一个block放不下,那就看你会存放到两个redo log block中。
- 如果一个redo log group比较小,那么可能会有多个redo log group的redo log 存到一个redo log block中。
1.6 redo log buffer中缓冲日志写入磁盘时机
- 如果写入redo log buffer的日志以及占据redo log buffer总容量的一半(默认总容量为16M)。此时Innodb存储引擎会自动将他们刷入到磁盘文件
- 当一个事务要提交是,为了保证事务的持久性,则也必须将它的redo log所在的redo log block刷入磁盘文件中(即使这个block没有写满)
- 后台线程也会定期将redo log buffer里的redo log block刷新到磁盘文件中(每隔一秒)
- MySQL关闭时,redo log block都会刷入到磁盘文件中
1.7 redo log磁盘文件
- 可以通过show variables like 'datadir'来查看redo log 磁盘文件的位置
- 可以通过innodb_log_group_home_dir参数来设置redo log磁盘文件的目录
- redo log 磁盘文件默认有2个,分别叫做ib_logfifile0和ib_logfifile1。每个大小固定48M。
- 可以通过参数innodb_log_fifile_size参数调整redo log 磁盘文件的个数
- redo log磁盘文件是循环写入,一个写满了就往下一个redo log磁盘文件写入。如果两个都写满了,则必须停止数据库更新操作,进行数据库脏页刷新。(这是数据库性能抖动的原因)
2. undo log
2.1 含义
- undo log 是逻辑日志。根据undo log日志你可以回溯到该记录之前的状态。
- 即在事务操作过程中,先对数据进行了修改,但是最后发生了事务回滚,则可以根据undo log将更新的数据回滚到事务开始之前的状态。
2.2 undo log的分类
- insert undo log
- 代表事务在insert新纪录时产生的undo log,在事务回滚时需要,当事务提交后就可以丢弃
- 对于insert undo log日志,会记录插入的记录ID,以便回滚的时候可以删除插入的记录
- update undo log
- 事务在update或delete时产生的undo log,不仅在事务回滚时会用到。在MVCC中的快照读也需要,不能随便删除。只有当快照读和事务回滚都不涉及该日志才可以被删除。
- 对于update undo log日志,会记录修改记录的旧值,如果事务回滚可以根据旧值得到之前的记录。
2.3 undo log的存储位置
- undo log日志的维护是按照回滚段的方式来维护的。回滚段是一种Undo文件组织方式。
- 每个回滚段又有多个undo log slot,而每个undo log slot对于一个undo log对象(Undo log header page)
- 回滚段rseg0预留在系统表空间ibdata中
- 回滚段rseg1~rseg32这32个回滚段存放于临时表的系统表空间
- 回滚段rseg33以上则根据配置存放到独立的undo表空间中。(如果没有打开独立Undo表空间,则存放在ibdata中)
- 每个回滚段维护了一个段头页,在该page中又划分了1024个slot,每个slot对应一个undo log对象,因此理论上InnoDB最多支持96*1024个普通事务。
- 当事务开启时,会专门给该事务指定一个回滚段,以后该事务用到的undo log页,就会从该回滚段上分配。
- 事务提交后,需要purge(清除)的回滚段会被放到purge队列上。
2.4 undo log 的记录了什么
- 事务id
- 表空间
- 记录编号(类似主键)
- 旧值(记录被修改的字段名与被修改的字段值)
- 日志类型(是update还是insert类型,update类型的日志有旧值)