MySQL中InnoDB脏页刷新机制Checkpoint

我们知道InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页。既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,那为什么还要刷新脏页到磁盘呢?如果重做日志可以无限增大,同时缓冲池足够大,能够缓存所有数据,那么是不需要将缓冲池中的脏页刷新到磁盘。但是,通常会有以下几个问题:

  • 服务器内存有限,缓冲池不够用,无法缓存全部数据
  • 重做日志无限增大成本要求太高
  • 宕机时如果重做全部日志恢复时间过长

事实上,当数据库宕机时,数据库不需要重做所有的日志,只需要执行上次刷入点之后的日志。这个点就叫做Checkpoint,它解决了以上的问题:

  • 缩短数据库恢复时间
  • 缓冲池不够用时,将脏页刷新到磁盘
  • 重做日志不可用时,刷新脏页

重做日志被设计成可循环使用,当日志文件写满时,重做日志中对应数据已经被刷新到磁盘的那部分不再需要的日志可以被覆盖重用。

InnoDB引擎通过LSN(Log Sequence Number)来标记版本,LSN是日志空间中每条日志的结束点,用字节偏移量来表示。每个page有LSN,redo log也有LSN,Checkpoint也有LSN。可以通过命令show engine innodb status来观察:

---
LOG
---
Log sequence number 11102619599
Log flushed up to   11102618636
Last checkpoint at  11102606319
0 pending log writes, 0 pending chkp writes
15416290 log i/o‘s done, 12.32 log i/o‘s/second

Checkpoint机制每次刷新多少页,从哪里取脏页,什么时间触发刷新?这些都是很复杂的。有两种Checkpoint,分别为:

  • Sharp Checkpoint
  • Fuzzy Checkpoint

Sharp Checkpoint发生在关闭数据库时,将所有脏页刷回磁盘。在运行时使用Fuzzy Checkpoint进行部分脏页的刷新。部分脏页刷新有以下几种:

  • Master Thread Checkpoint
  • FLUSH_LRU_LIST Checkpoint
  • Async/Sync Flush Checkpoint
  • Dirty Page too much Checkpoint

Master Thread Checkpoint

Master Thread以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘。这个过程是异步的,不会阻塞查询线程。

FLUSH_LRU_LIST Checkpoint

InnoDB要保证LRU列表中有100左右空闲页可使用。在InnoDB1.1.X版本前,要检查LRU中是否有足够的页用于用户查询操作线程,如果没有,会将LRU列表尾端的页淘汰,如果被淘汰的页中有脏页,会强制执行Checkpoint刷回脏页数据到磁盘,显然这会阻塞用户查询线程。从InnoDB1.2.X版本开始,这个检查放到单独的Page Cleaner Thread中进行,并且用户可以通过innodb_lru_scan_depth控制LRU列表中可用页的数量,默认值为1024。

Async/Sync Flush Checkpoint

是指重做日志文件不可用时,需要强制将脏页列表中的一些页刷新回磁盘。这可以保证重做日志文件可循环使用。在InnoDB1.2.X版本之前,Async Flush Checkpoint会阻塞发现问题的用户查询线程,Sync Flush Checkpoint会阻塞所有查询线程。InnoDB1.2.X之后放到单独的Page Cleaner Thread。

Dirty Page too much Checkpoint

脏页数量太多时,InnoDB引擎会强制进行Checkpoint。目的还是为了保证缓冲池中有足够可用的空闲页。其可以通过参数innodb_max_dirty_pages_pct来设置:

mysql> show variables like ‘innodb_max_dirty_pages_pct‘;
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| innodb_max_dirty_pages_pct | 90    |
+----------------------------+-------+
时间: 2024-10-01 02:55:49

MySQL中InnoDB脏页刷新机制Checkpoint的相关文章

InnoDB脏页刷新机制Checkpoint

我们知道InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页.既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,那为什么还要刷新脏页到磁盘呢?如果重做日志可以无限增大,同时缓冲池足够大,能够缓存所有数据,那么是不需要将缓冲池中的脏页刷新到磁盘.但是,通常会有以下几个问题: 服务器内存有限,缓冲池不够用,无法缓存全部数据 重做日志无限增大成本要求太高 宕机时如果重做全部日志恢复时间过长 事实上,当数据库

InnoDB Redo Flush及脏页刷新机制深入分析

概要: 我们知道InnoDB采用Write Ahead Log策略来防止宕机数据丢失,即事务提交时,先写重做日志,再修改内存数据页,这样就产生了脏页.既然有重做日志保证数据持久性,查询时也可以直接从缓冲池页中取数据,那为什么还要刷新脏页到磁盘呢?如果重做日志可以无限增大,同时缓冲池足够大,能够缓存所有数据,那么是不需要将缓冲池中的脏页刷新到磁盘.但是,通常会有以下几个问题: 服务器内存有限,缓冲池不够用,无法缓存全部数据 重做日志无限增大成本要求太高 宕机时如果重做全部日志恢复时间过长 事实上,

MYSQL的InnoDB Buffer Pool内部机制

1. 基本结构:INNODB用least recently used (LRU) 算法来管理他的buffer_pool. buffer_pool在内部被分隔为两个list. a young list 和 a old list. Young list 存储那些高频使用的缓存数据(默认占整个BUFFER的5/8) Old list 存储那些低频使用的数据(默认占整个BUFFER的3/8) 2.使用机制:当一个新块数据被从磁盘缓存到buffer当中,它默认被放在Old list的头部,即midpoin

MYSQL中InnoDB特性浅谈

许久没有更新博客,上周末放假把网易大牛姜sir的著作MYSQL技术内幕InnoDB存储引擎又翻阅了一番,对当前工作的InnoDB特性有了一些新的认识,下面谈谈自己的读后感. 1. InnoDB的体系架构由一系列后台线程,内存池和文件组成,这点与其他DB有相似之处. 在内存中划分了一块区域,即缓冲池,用来临时存放用户读写的数据页. InnoDB上对缓冲池读写数据页,刷新到磁盘等操作也使用了CHECKPOINT机制,LRU算法,这点与SQLSERVER,DB2等数据库设计一致,这里不再阐述.需要注意

Mysql的刷脏页问题

平时的工作中,不知道你有没有遇到过这样的场景,一条 SQL 语句,正常执行的时候特别快,但是有时也不知道怎么回事,它就会变得特别慢,并且这样的场景很难复现,它不只随机,而且持续时间还很短. 当内存数据页跟磁盘数据页内容不一致的时候,我们称这个内存页为“脏页”.内存数据写入到磁盘后,内存和磁盘上的数据页的内容就一致了,称为“干净页”. 平时执行很快的更新操作,其实就是在写内存和日志,而 MySQL 偶尔“抖”一下的那个瞬间,可能就是在刷脏页(flush). 那么,什么情况会引发数据库的 flush

mysql 学习 - InnoDB的页

页 InnoDB是一个将表中的数据存储到磁盘上的存储引擎,所以即使关机后重启我们的数据还是存在的.而真正处理数据的过程是发生在内存中的,所以需要把磁盘中的数据加载到内存中,如果是处理写入或修改请求的话,还需要把内存中的内容刷新到磁盘上. 不论是读取数据还是写入数据, InnoDB 引擎是以页为单位操作的. 将数据划分为若干个页,以页作为磁盘和内存之间交互的基本单位,InnoDB中页的大小一般为 16 KB.也就是在一般情况下,一次最少从磁盘中读取16KB的内容到内存中,一次最少把内存中的16KB

MySQL中InnoDB存储引擎中的哈希算法

InnoDB存储引擎使用哈希算法来对字典进行查找,其冲突机制采用链表方式,哈希函数采用除法散列方式.对于缓冲池页的哈希表来说,在缓冲池中的Page页都有一个chain指针.它指向相同哈希函数值的页的.而对于除法散列,m的取值略大于2倍的缓冲池页数量的质数.例如:当前参数innodb_buffer_pool_size的大小为10M,则共有640个16kb的页.对于缓冲池页内存的哈希表来说,需要分配640*2=1280个槽,但是由于1280不是质数,需要取比1280略大的一个质数,应该是1399,所

MySQL中innodb引擎分析(初始化)

MySQL的存储引擎是以插件形式工作的,这应该是MySQL的一大特色了吧! 依据<深入理解MySQL>的内容,5.1版本号时存储引擎的插件化都还不是彻底,确切的说是刚加入的特性.为MySQL加入一个存储引擎时,须要更改一些上层代码,零散的更改本来就有点麻烦,同一时候project也要又一次编译一次.我听别人说,已经能够不改C/C++代码就直接加入引擎了.这种话,折腾存储引擎的话就更方便了! 这段代码来自ha_innodb.cc,这是MySQL中申明存储引擎插件的标准过程.这段代码利用了宏.在p

linux中的脏页写回

为了减轻内存使用的压力,除了用户手动写回脏页以外,还有一些机制触发脏页写回. 比方说设置定时器,定期写回脏了很久的页. 具体介绍下面的写回机制,因为这种机制不像写回脏了很久的页的机制那样被动. wakeu_bdflush 复杂唤醒写回的核心函数. 能触发此函数条件,可能会是以下几点中的一点会多: 1.用户态进程调用sync强制写回 2.grow_buffers()分配一个新的缓冲区页失败时 .此时的页中缓冲区块大小与要求的不同,因此要释放掉. 3.页框回收算法调用free_more_memoy(