编程技术分享平台

网站首页 > 技术教程 正文

MySQL Innodb的checkpoint 和 flush 机制

xnh888 2024-11-05 12:55:22 技术教程 16 ℃ 0 评论

buffer pool中的页面共有3种类型:

1、free:当前page未被使用;

2、clean:当前page被使用,并且对应数据文件中的一个页面,但页未被修改;

3、dirty:当前page被使用,并且对应数据文件中的一个页面,同时页面已经被修改,还没有刷到磁盘上。

free类型的页面一定在free list中,dirty/clean类型的页面一定在lru list中。dirty page也包含在flush list中。

dirty类型的页需要定的flush到磁盘上。主要有2个原因:

1、当innodb 需要将磁盘上的一个page读到内存中时,发现没有空闲page。这个时候需要从innodb LRU list中选择一个脏页,并刷到磁盘上。

这种刷脏也被称为 LRU_list flush。

2、innodb需要重用redo logs,也需要进行flush操作。innodb中的redo是循环使用的,只有redo对应的dirty page已经被刷到磁盘上了,这些redo才能被重用。

这种刷脏也被称为 flush_list flush。

flush_list flush出现在下面4种情况下:(syc_water_mark = redo size * 0.81 * 15/16; asyc_water_mark = redo size * 0.81 * 7/8)

1、checkpoint_age < async_water_mark

master thread 在后台进行,不影响用户线程

2、async_water_mark < checkpoint_age < syc_water_mark

用户线程发现满足这种条件,会主动进行flush,这种情况下,进行flush的用户线程会收到影响,而其他用户线程(不进行flush操作的)不会受到影响。

3、checkpoin_age > sync_water_mark

这种情况下的flush,所有用户查询都会受到影响,并且会引起系统抖动

4、%n_dirty_pages > innodb_max_dirty_page_pct

当buffer pool中dirty pages的比例超过了innodb_max_dirty_page_pct之后,innodb开始flush,这种flush在后台进行,不会阻塞用户线程。

checkpoint:出于性能上的考虑,buffer pool中的page被修改后,并不会马上刷到磁盘上,而是通过flush机制来进行的。checkpoint就是最近一次被刷到磁盘上的数据对应的LSN信息。(http://dev.mysql.com/doc/refman/5.6/en/glossary.html#glos_checkpoint)。

innodb的checkpoint机制分为fuzzy checkpoint/sharp checkpoint。

1、innodb每次根据flush list进行刷脏,其实就是在做checkpoint:向前推进系统的lsn。fuzzy checkpoint就是这样实现的。

2、innodb关闭的时候,停止更新,并且把所有脏页刷到磁盘上;然后把当前的lsn写到redo中。这就是sharp checkpoint。

fuzzy checkpoint发生的几种情况:(5.6.2之前)

1、master thread checkpoint,每秒或每10秒进行一次,不影响用户线程。

2、async/sync flush checkpoint,重做日志不可用的情况,这时需要强制将一些页刷新回磁盘,而此时脏页是从flush list中选取的。

将已写入redo的lsn记为redo_lsn,将已经刷新回磁盘最新页的lsn记为checkpoint_lsn,则有下面的公式:

checkpoing_age = redo_lsn - checkpoint_lsn

async_watermark = 75% * total_redo_log_file_size

sync_watermark = 90% total_redo_file_size

3、FLUSH_LRU_LIST checkpoint,innodb存储引擎需要保证LRU链表和free链表中至少有BUF_FLUSH_FREE_BLOCK_MARGIN + BUF_FLUSH_EXTRA_MARGIN (146) 个可被立即使用的页。

从5.6.2开始,innodb新增了一个page_cleaner的后台线程,专门处理flush操作,之前的版本中,需要在master thread中进行的adaptive flushing,用户线程进行的async flushing,idle flushing,关机时的flush都在page_cleaner线程中进行;只有sync flushing还是由用户线程中触发。

checkpoint信息更新:(5.6.2之前)

1、每1S。若buffer pool中的脏页比例超过75%(srv_max_buf_pool_modified_pct,这个值对应于innodb_max_dirty_pages_pct,如果设置了innodb_max_dirty_pages_pct就按

设置的阀值进行flush),则进行checkpoint,刷脏页,flush 200(PCT_IO(100))个 dirty pages

若采用adaptive flushing,则计算flush rate,进行必要的flush

2、每10S。每10S进行一次刷脏;然后调用一次log_checkpoint, 做一次checkpoint(检查the oldest lsn,并且更新lsn信息)

若buffer pool中的脏页比率超过了70%(这个比例目前是代码中写死的),flush PCT_IO(100)的dirty pages;

若buffer pool中的脏页比例未超过70%(这个比例目前是代码中写死的),flush PCT_IO(10)的dirty pages;

Q: 脏页比例的是如何计算的?

A:脏页比率 = 需要被flush的页面数/(使用中的页面数 + 空闲页面数 + 1)。

Q:adaptive flushing时如何计算flush rate:(buf_flush_get_desired_flush_rate():buf0flu.c)

A:

1、循环每个buffer pool instance,计算dirty page的数量。

/* Get total number of dirty pages. It is OK to access

flush_list without holding any mutex as we are using this

only for heuristics. */

for (i = 0; i < srv_buf_pool_instances; i++) {

buf_pool_t* buf_pool;

buf_pool = buf_pool_from_array(i);

n_dirty += UT_LIST_GET_LEN(buf_pool->flush_list)

}

2、计算最近一段时间(BUF_FLUSH_STAT_N_INTERVAL),redo产生的平均速度。

/* redo_avg below is average at which redo is generated in

past BUF_FLUSH_STAT_N_INTERVAL + redo generated in the current

interval. */

redo_avg = (ulint) (buf_flush_stat_sum.redo

/ BUF_FLUSH_STAT_N_INTERVAL

+ (lsn - buf_flush_stat_cur.redo));

3、计算过去一段时间(BUF_FLUSH_STAT_N_INTERVAL),lru list flush的平均速度。

/* lru_flush_avg below is rate at which pages are flushed as

part of LRU flush in past BUF_FLUSH_STAT_N_INTERVAL + the

number of pages flushed in the current interval. */

lru_flush_avg = buf_flush_stat_sum.n_flushed

/ BUF_FLUSH_STAT_N_INTERVAL

+ (buf_lru_flush_page_count

- buf_flush_stat_cur.n_flushed);

4、计算本次flush list flush需要flush的脏页数量。

n_flush_req = (n_dirty * redo_avg) / log_capacity;

/* The number of pages that we want to flush from the flush

list is the difference between the required rate and the

number of pages that we are historically flushing from the

LRU list */

rate = n_flush_req - lru_flush_avg;

5、flush list flush最终flush的脏页数量,最大是200个脏页。

/* Try to keep the rate of flushing of dirty

pages such that redo log generation does not

produce bursts of IO at checkpoint time. */

ulint n_flush = buf_flush_get_desired_flush_rate();

if (n_flush) {

srv_main_thread_op_info =

"flushing buffer pool pages";

n_flush = ut_min(PCT_IO(100), n_flush);

n_pages_flushed =

buf_flush_list(

n_flush,

IB_ULONGLONG_MAX);

}

1) free page: this page is not in use, this type of page is located in the free linked list

2) clean page: This page is used, the corresponding data file of a page, but the page has not been modified, this type of page is located in the LRU linked list

3) dirty page: This page is used, the corresponding data file in a page, but the page has been modified, this type of page is located in the LRU lists and flush linked list

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表