MySQLLSN 详解,以及进行crash recovery原理

LSN概念
LSN 称为日志的逻辑序列号(log sequence number)在InnoDB存储引擎中,LSN占8个字节,LSN的值会随着日志的写入而逐渐变大。

根据LSN,可以获取到几个有用的信息:

数据页的版本信息。
写入的日志总量。通过LSN开始号码和结束号码可以计算出写入的日志量。
可知道检查点的位置。
实际上还可以获得很多隐式的信息。

LSN 不仅存在于redo log中,还存在于数据页中,在每个数据页的头部FILE_HEADER部分,有一个FIL_PAGE_LSN ---记录了该数据页最后被修改的日志序列位置。通过数据页中的LSN值和redo log中的LSN值比较,如果页中的LSN值小于redo log中LSN值,则表示数据丢失了一部分,这时候可以通过redo log的记录来恢复到redo log中记录的LSN值时的状态。

查看Redo日志的LSN

redo log的LSN信息可以通过 show engine innodb status 命令来查看。 (MySQL-8.0.26-debug)
---
LOG
---
Log sequence number 99376041
Log flushed up to   99376041
Pages flushed up to 99376041
Last checkpoint at  99376032

log sequence number 就是当前的 redo log (in buffer) 中的 LSN;
log flushed up to 是刷到 redo log file 磁盘数据中的 LSN;
pages flushed up to 是已经刷到磁盘数据页上的 LSN;
last checkpoint at 是上一次检查点所在位置的 LSN。(page_cleaner_thread线程就会把上面的数据不一致进行刷新同步,刷新一次就会记录一个检查点(checkpoint),可以理解检查点checkpoint是动态更新的,checkpoint变量存储的变量就是当前的LSN。)

下面测试可以看到插入一行和两行数据后,LSN的变化。
mysql> insert into employee values (32,'asfsf');
Query OK, 1 row affected (0.01 sec)
---
LOG
---
Log sequence number 99378739
Log flushed up to   99378739
Pages flushed up to 99378739
Last checkpoint at  99378730

mysql> insert into employee values (33,'asfsf'); 
Query OK, 1 row affected (0.00 sec)

mysql> insert into employee values (34,'asfsf'); 
Query OK, 1 row affected (0.00 sec)

LOG
---
Log sequence number 99382498
Log flushed up to   99382498
Pages flushed up to 99382498
Last checkpoint at  99382489
0 pending log flushes, 0 pending chkp writes

从执行修改语句开始看InnoDB引擎的执行过程
首先修改内存中的数据页,并在数据页中记录LSN,暂且称之为 data_in_buffer_lsn;
并且在修改数据页的同时(几乎是同时)向redo log in buffer中写入redo log,并记录下对应的LSN,暂且称之为redo_log_in_buffer_lsn;
写完buffer中的日志后,当触发了日志刷盘的几种规则时,会向redo log file on disk刷入Redo日志,并在该文件中记下对应的LSN,暂且称之为 redo_log_on_disk_lsn;
数据页不可能永远只停留在内存中,在某些情况下,会触发checkpoint来将内存中的脏页(数据脏页和日志脏页)刷到磁盘,所以会在本次checkpoint脏页刷盘结束时,在redo log中记录checkpoint的LSN位置,暂且称之为checkpoint_lsn。
要记录checkpoint所在位置很快,只需简单的设置一个标志即可,但是刷数据页并不一定很快,例如这一次checkpoint要刷入的数据页非常多。也就是说,要刷入所有的数据页需要一定的时间来完成,中途刷入的每个数据页都会记下当前页所在的LSN,暂且称之为 data_page_on_disk_lsn。

脏页刷到磁盘的触发条件:
我们都知道我们执行更新操作,更改的是Buffer Pool中的页,该页再变为脏页,脏页刷新回磁盘是使用的CheckPoint技术,接下来就是脏页刷新回磁盘的一些触发条件:

1.Master Thread 以秒为单位按一定条件刷新脏页(如果对IndoDB的Master Thread不了解的可以点击查看该文章,该文章详细介绍了Master Thread的执行流程)
2.LRU 列表剩余空闲页不足100时,就移除LRU尾端的页,如果该页是脏页就会执行Check Point 刷新脏页
3.Buffer Pool中脏页所占空间达到了Buffer Pool的总容量的75%也会刷新脏页
4.Redo Log持久化文件中,未将脏页刷新回磁盘的Redo Log所占空间达到了总Redo Log持久化文件的75%

Redo Log刷到磁盘的触发条件:
当我们执行更新语句后,会先生成Redo Log,再修改页,当数据库宕机后还有一些脏页未刷新会磁盘,就会造成数据的丢失,可以通过Redo Log来进行数据恢复,关于Redo Log 从内存中刷新至磁盘以及Redo Log持久化文件的清理工作:

1.Master Thread 以秒为单位将内存中的Redo Log 刷新回磁盘文件中
2.事务提交,对应的Redo Log刷新回磁盘文件中
3.Redo Log缓冲池中Redo Log所占空间超过总缓冲池中的空间的1/2回将Redo Log刷新回磁盘文件
4.Redo Log持久化文件中会有被重用的部分允许覆盖重用,当不可重用的部分所占空间超过了总文件空间的75%时,会刷新Buffer Pool中的脏页,进而让Redo Log持久化文件中有更多的可重用部分。
 

如何crash recovery?是哪个LSN开始redo?
crash recovery的第一阶段是回放redo log以将磁盘上的数据页面恢复至最新状态,而回放的起始位点就是实例退出前记录的checkpoint lsn。因为checkpoint lsn保证了这之前的redo log对应的page更改一定已经被持久化。MYSQL中如果一个事务没有提及,那脏页就不会刷到磁盘持久化,这一点和DB2是有区别的,逻辑更简单。
但是容易出现一个问题,就是一个很久的事务一直不提交或者忘了提交吗,那mysql+脏页过多导致缓存满了+但是事务还未提交+还不能刷盘+怎么办?
这种情况可能会导致MySQL出现性能问题或者宕机,只能手动提交事务或者回滚

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值