innodb 刷数据

首先innodb 线程分为用户态线程和后台线程,用户态线程主要是用户操作的线程,可以通过show process list 查看,后台线程不能够查看。但是show innodb status可以查看到4个线程

I/O thread 0 state: waiting for i/o request (insert buffer thread)
I/O thread 1 state: waiting for i/o request (log thread)
I/O thread 2 state: waiting for i/o request (read thread)
I/O thread 3 state: waiting for i/o request (write thread)

IO线程是可以通过innodb_file_io_threads  参数配置,默认是4;

其次innodb 刷数据也分两种,同步IO及一步IO就是show innodb status 中出现的aio;


在innodb中后台线程刷数据时异步IO,后台线程受主线程master_thread调度;master_thread 优先级最高,其内部由几个循环构成

主 loop ,background loop,flush loop;suspend loop;master thread 运行会在这几个线程之间切换;


首先说  主loop,主loop 分为两类主要操作,每1s和每10s,但是innodb 并不是严格按照这个时段来执行的,因为中间出了切换还有sleep等操作会消耗时间;

在innodb中维护了4个队列,每个队列长度256,其中存放的是slot,当队列满时,必然会唤醒相关的IO线程执行相应的iO操作,主线程也会周期性的唤醒IO线程;然后检查自己的队列,看是否需要做刷盘操作; 这4个线程是异步IO;


每1s唤醒IO线程执行操作

1、日志缓冲刷新到磁盘,每1s 执行,同时日志缓冲会受到innodb_flush_log_at_trx_commit  参数配置的影响,但是即使事务没有提交,也会刷,在刷日志时,innodb会对时间做一个判断,首先先看有没有在队列里超过2s的 如果有 就先刷他们,如果没有超过2s的 也先刷低地址的,然后会遍历队列 把几个在同一个extent的page一起刷下去;

2、合并插入缓冲(可能);innodb会判断当前IO情况,如果当前1s内少于5次IO,它就认为当前IO负载较小,执行合并插入;

3、刷新至多100个脏数据页(可能);如果当前脏页操过了90%,就是innodb_max_dirty_pages_pct 默认值,那么它认为需要刷新脏页

4、切换到background loop;


每10s唤醒IO线程执行的操作

1、将日志缓冲刷新到磁盘;

2、合并5个插入缓冲;不管当前IO操作能力如何,总是强制执行;

3、刷新100个脏页;innodb会判断过去10s内IO操作是否小于200,如果是,那么它认为当前IO比较轻,执行刷新100个脏页;如果当前脏页比例大于70%,那么也会刷新100个脏页,否则会刷新10个;

4、删除无用的undo页;因为innodb采用了MVCC机制,有些为了一致性读而被标记为删除状态数据页需要被清理,比如有时一个查询可能需要读取前一个版本的数据信息,它被放在undo页中;但是每次最多删除20个undo页;

5、产生一个检查点;innodb 刷数据时会产生一个检查点;但是没10s也会强制产生一个检查点;为了保证性能,并不是完全刷完脏数据,而是志将最老日志序列号的页刷盘;



background loop ,当前没有或用用户或者数据库关闭时就会切换到这个循环;

它会执行以下操作;

1、删除无用的 undo页;

2、合并20个插入缓冲;

3、不断刷新100个数据页,知道符合条件(可能跳到  flush loop 中完成);


suspend_loop

如果 flush loop中也没有什么事情可以做了,innodb 会切换到 suspeng_loop,将master thread挂起,等待事件的发生;如果启用了innodb 存储引擎却没有innodb表,通用也会将 master thread 挂起;


主线程如下

 void master_thread(){  
 2     goto loop;  
 3 loop:  
 4 for(int i = 0; i<10; i++){  
 5     thread_sleep(1) // sleep 1 second  
 6     do log buffer flush to disk  
 7     if ( last_one_second_ios < 5 )  
 8         do merge at most 5 insert buffer  
 9     if ( buf_get_modified_ratio_pct > innodb_max_dirty_pages_pct )  
10         do buffer pool flush 100 dirty page  
11     if ( no user activity )  
12         goto backgroud loop  
13 }  
14 if ( last_ten_second_ios < 200 )  
15     do buffer pool flush 100 dirty page  
16 do merge at most 5 insert buffer  
17 do log buffer flush to disk  
18 do full purge  
19 if ( buf_get_modified_ratio_pct > 70% )  
20     do buffer pool flush 100 dirty page  
21 else  
22     buffer pool flush 10 dirty page  
23 do fuzzy checkpoint  
24 goto loop  
25 background loop:  
26 do full purge  
27 do merge 20 insert buffer  
28 if not idle:  
29 goto loop:  
30 else:  
31     goto flush loop  
32 flush loop:  
33 do buffer pool flush 100 dirty page  
34 if ( buf_get_modified_ratio_pct> innodb_max_dirty_pages_pct )  
35     goto flush loop  
36 goto suspend loop  
37 suspend loop:  
38 suspend_thread()  
39 waiting event  
40 goto loop;  

后续会对innodb plugin 说明


上面说到 的主线程部分大多数是异步IO ,但是用户态线程大多数是同步IO;

当你发起一个事务时,innodb会判断log buffer 是否有足够的空间;如果有那么就启动一个事务,如果没有,那么就会唤醒log thread 刷日志,但是并不刷完;同时也会对脏页做类似处理;


参考 innodb 存储引擎内幕一书及自己一些学习;






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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值