1.redo日志的存储
redo日志记录的存储载体是log block(和页相似),每个块512字节,其结构如下
2. redo日志的缓存
服务器启动时会向内存申请一大片成为redo log buffer的连续内存空间,被划分成若干redo log block
1.日志缓冲区的存储形式
一个事务中的一个sql语句可能包含多个原子操作,对应多条mtr,这些mtr对应的redo日志组可以交替写入缓存区,但一个日志组内的redo记录必须在一块.
2. 缓冲区redo日志的刷盘时机
- 缓冲区内的日志量占总容量的50%
- 事务提交时 事务提交时,可以不把事务对应的脏页刷入,但是其对应的redo日志要刷新到磁盘,防止此时断电
- 将某个脏页刷新到磁盘前,应该是防止该脏页刷新失败
- 后台线程每秒一次的频率刷新
- 正常关闭服务器时
- check point
3. 查看本地日志文件
mysql> show variables like 'datadir';
+---------------+---------------------------------------------+
| Variable_name | Value |
+---------------+---------------------------------------------+
| datadir | C:\ProgramData\MySQL\MySQL Server 5.5\Data\ |
+---------------+---------------------------------------------+
1 row in set (0.00 sec)
4. redo 日志文件的格式
每个日志文件的前四个块不记录实际数据,用来存储一些管理信息,其它块存储log buffer中的block的镜像.
5. lsn 脏页 与checkpoint的关系
页面缓冲池中保存页面和页控制块,页控制块包含属性
oldest_modification: 第一次修改该页面开始时间(头lsn)
newest_modification: 最后一次修改页面的结束时间(尾lsn)
页控制块信息如下:
在队尾的元素一定是最先修改的页面,小于其对应的o_m对应的页面一定已经被刷新到磁盘中(或者根本不是脏页),那么在日志文件中的日志记录就可以被覆盖(因为对页面的修改已经刷入磁盘).我们使用checkpoint_lsn指向日志文件中可以被覆盖的日志记录末尾.刷盘时,如果首先刷的是c和d(没有从队头刷),此时最小o_m仍然是8716,虽然checkpoint_lsn右边的某些mtr对应的脏页已全部刷盘,如果checkpoint_lsn移动到此,不能保证checkpoint_lsn前面所有mtr对应的所有脏页已经刷盘(a没有刷).
如果我们对a刷盘,此时日志缓冲区,日志文件,文件缓冲区的状态如下
重要结论:
-
lsn的值越小,该mtr写入log buffer的时间越早,因为lsn是递增的
-
如果最新lsn与flushed_to_disk_lsn相等,说明缓冲池中所有日志mtr都被写入到日志文件中
-
mtr在日志文件中的偏移量与lsn具有映射关系
-
mtr执行结束,会把该mtr执行过程中修改的脏页加入到flush链表的头部,flush链表中,越靠近头,第一次修改该页面的时间就越晚,其o_m越大,n_m也大,最后一次修改该页面的时刻越晚.o_m在flush链表中是从尾到头是递增的
-
刷盘和执行checkpoint分开执行,没有联系,可能刷新多次才更新一次checkpoint(a-b-c,checkpoint指向c包含checkpoint指向a)
-
checkpoint_sln前面的mtr对应的脏页一定已经刷新到磁盘,后面的lsn对应的脏页可能部分已经刷新到磁盘,也可能没有
6. 实验:查看系统各lsn的值
show engine innodb status;
Log sequence number 60740505 //当前系统(缓冲池)lsn的值
Log flushed up to 60740505 //缓冲池中已刷新 flushed_to_disk_lsn
Last checkpoint at 60740505 // 日志文件中 check_point 的值
Pages flushed up to // flush链表中最早被修改的脏页对应的lsn