21. CheckPoint
CheckPoint的作用
- 缩短数据库的恢复时间
- 数据库宕机恢复依赖redo log。当恢复时不需要重做所有日志,因为CheckPoint之前的页都已经刷盘,只需要对CheckPoint之后的日志进行恢复,从而缩短恢复时间
- 缓冲池不够用时,将脏页刷新到磁盘
- 当缓冲池不够时,LRU算法会溢出最近最少使用的页,若此页为脏页,会强制CheckPoint,将该脏页刷回到磁盘
- 重做日志不可用时,刷新脏页
- 不可用是因为对重做日志的设计是循环使用。重做日志可以被重用的部分,是指当数据库恢复时不需要的部分。若此时这部分重做日志还有用,则强制执行CheckPoint,将缓冲池的页刷新至少刷新到磁盘
- 数据页首先被读入BP中,当数据页中的某几条记录被更新或者插入新的记录时,所有的操作都是在Buffer Pool 先完成的;
- Buffer Pool中的某个页和磁盘中的某个页在(Space, Page_Number)上是相同的,但是其内容可能是不同的(Buffer Pool中的被更新过了),形成了脏页;
- 要定期将缓冲池中的脏页刷回磁盘(Flush),达到最终一致,即通过CheckPoint机制来刷脏页;
LSN
root@mysqldb 14:46: [(none)]> show engine innodb status\G
-- 省略其他
---
LOG
---
Log sequence number 5552603620 -- 当前内存中最新的LSN
Log buffer assigned up to 5552603620
Log buffer completed up to 5552603620
Log written up to 5552603620
Log flushed up to 5552603620 -- redo刷新到磁盘的LSN
Added dirty pages up to 5552603620
Pages flushed up to 5552603620 -- 最后一个刷新到磁盘上的页的最新的LSN(NEWEST_MODIFICATION)
Last checkpoint at 5552603620 -- 最后一个刷新到磁盘上的页的第一次被修改的LSN(OLDEST_MODIFICATION)
Log minimum file id is 41
Log maximum file id is 41
32 log i/o's done, 0.00 log i/o's/second
- LSN(Log Sequence Number) 是一个字节数。
- Log sequence number 和 Log flushed up 这两个LSN可能会不同,运行过程中后者可能会小于前者,因为redo日志也是先在内存中更新,再刷到磁盘的。
- Pages flushed up 与 Last checkpoint 其实都指向了最后一个刷新到磁盘的页,只是 Pages flushed up 代表了页中的 NEWEST_MODIFICATION,而 Last checkpoint 代表了页中的 OLDEST_MODIFICATION。
- FLUSH LIST 使用 OLDEST_MODIFICATION 进行记录并排序,那在刷新脏页时, CheckPoint 的 LSN 值就对应的是 当前刷新到某个页 的 OLDEST_MODIFICATION ;
- 当某个页只被修改过一次,则 Pages flushed up 与 Last checkpoint 会相等,反之多次修改,则 Pages flushed up 大于 Last checkpoint;
- 在恢复时,从 CheckPoint 开始恢复,如果当前页的LSN大于CheckPoint的LSN,则表示不需要恢复了;(https://www.cnblogs.com/DataArt/p/10236642.html)
日志(redo)中的LSN
- 假设当前的LSN为 C ,此时对某个页做修改,则会产生 M 个字节的日志(需要写入M个字节的日志),那此时的 LSN 则为 C+M 。依次类推,LSN是一个 单调递增 的值(字节数)。
- 日志中的LSN代表了日志一共写入了多少个字节。
页中的LSN
页中也存在LSN,表示该页被修改的时候,对应的日志的LSN是多少;
root@mysqldb 15:05: [(none)]> desc information_schema.INNODB_BUFFER_PAGE_LRU;
+---------------------+-----------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+-----------------+------+-----+---------+-------+
| POOL_ID | bigint unsigned | NO | | | |
| LRU_POSITION | bigint unsigned | NO | | | |
| SPACE | bigint unsigned | NO | | | |
| PAGE_NUMBER | bigint unsigned | NO | | | |
| PAGE_TYPE | varchar(64) | YES | | | |
| FLUSH_TYPE | bigint unsigned | NO | | | |
| FIX_COUNT | bigint unsigned | NO | | | |
| IS_HASHED | varchar(3) | YES | | | |
| NEWEST_MODIFICATION | bigint unsigned | NO | | | | -- 该页最近一次(最新)被修改的LSN值
| OLDEST_MODIFICATION | bigint unsigned | NO | | | |
| ACCESS_TIME | bigint unsigned | NO | | | | -- 该页在Buffer Pool中第一次被修改的LSN值
| TABLE_NAME | varchar(1024) | YES | | | |
| INDEX_NAME | varchar(1024) | YES | | | |
| NUMBER_RECORDS | bigint unsigned | NO | | | |
| DATA_SIZE | bigint unsigned | NO | | | |
| COMPRESSED_SIZE | bigint unsigned | NO | | | |
| COMPRESSED | varchar(3) | YES | | | |
| IO_FIX | varchar(64) | YES | | | |
| IS_OLD | varchar(3) | YES | | | |
| FREE_PAGE_CLOCK | bigint unsigned | NO | | | |
+---------------------+-----------------+------+-----+---------+-------+
20 rows in set (0.01 sec)