diff --git a/mysql/mysql文档/mysql_事务.md b/mysql/mysql文档/mysql_事务.md index 6329c02..df18058 100644 --- a/mysql/mysql文档/mysql_事务.md +++ b/mysql/mysql文档/mysql_事务.md @@ -201,3 +201,54 @@ redo log头部格式通常包含3部分: 之后redo log body部分,根据重做日志类型的不同会存储不同内容。 +#### LSN +LSN代表的是日志序列号,其大小为8字节,且单调递增。`LSN代表事务写入redo log的总字节数`。 + +##### 页LSN +在每个页的头部,都存在`FIL_PAGE_LSN`,其记录了该页的lsn。在页中,`LSN`代表该页最后刷新时的lsn大小。 + +FIL_PAGE_LSN在`buffer pool page`和`disk page`中均存在,二者记录的值不同: +- `buffer pool page` header中`FIL_PAGE_LSN`记录的是`内存页最后被修改的LSN` +- `disk page` header中`FIL_PAGE_LSN`记录的是最后被刷新到磁盘的页对应的最大修改LSN + +在执行crash recovery过程中,会从CHECKPOINT开始,一直到redo log file末尾,逐条处理redo log record,对于每条redo log record关联的页,会比较`record_lsn`和`FIL_PAGE_LSN`的大小: +- `record_lsn <= FIL_PAGE_LSN`:代表当前redo record对应的修改已经包含在页中,当前redo log record直接跳过即可 +- `record_lsn > FIL_PAGE_LSN`:代表当前redo record中的修改不存在于页中,需要对页应用record修改,并在修改完后更新页的`FIL_PAGE_LSN` + +##### 查看LSN +可以通过`show engine innodb status`来查看LSN情况,核心数值如下: +- `log sequence number`:代表当前LSN +- `log flushed up to`: 代表已经刷新到磁盘文件中的LSN +- `last checkpoint at`: 代表页已经刷新到磁盘的LSN + +#### recovery +innodb在启动时,`不管上次数据库运行是否正常关闭,都会尝试执行恢复`。 + +`redo log是物理日志,故而恢复速度相较逻辑日志要快得多`,恢复操作仅需从`checkpoint`开始。 + +例如,对于如下数据表 +```sql +create table t ( + a int, + b int, + primary key(a), + key(b) +); +``` +若执行sql语句 +```sql +insert into t select 1,2; +``` +在执行时,需要修改如下内容: +- 聚簇索引页(包含数据) +- 辅助索引页 + +故而,其记录重做日志内容大致为 +``` +page(2,3), offset 32, value 1,2; # 聚簇索引页 +page(2,4), offset 64, value 2; # 辅助索引页 +``` +由上述示例可知,redo log为物理日志,记录的是对页的物理修改,故而`redo log是幂等的`。 + + +