代码改变世界

innodb之线程及IO相关参数介绍

2018-12-12 15:04  烟雨楼人  阅读(4010)  评论(0编辑  收藏  举报

引用链接:http://www.cnblogs.com/henglxm/p/4284504.html

 

1.IO THREAD: 负责IO的相关线程IO THREAD

1. 参数innodb_write_io_threads  写线程 默认四个,负责数据块的写入

2. 参数innodb_read_io_threads 读线程  默认四个,负责数据块的读取

上面两个参数高并发下,可以设置为8.

show variables like '%write_io%'

show variables like '%read_io%'

也可通过mysql> show engine innodb status\G;查看IO thread.

 

2.Purge thread

作用真正的删除记录和删除undo log

 1.清理删除后的数据页的空间(因为之前的删除只是打上删除标签,并没有正真删除),

 2.清理undo

举例:tb1中有记录pk=123;

此时delete from tb1 where pk=1;

1. pk=1的记录标记为删除(delete-markinfobits),数据库中pk=1的记录此时还是存在的,空间并没有被释放,该操作为同步操作(SQL执行完,也就标记完成了)

2. purge ,该部分为后台线程(purge线程)异步操作,会真正的删除该记录,且空间被释放。

标记为已删除的原因:

1. 该事物可能需要回滚,先作保留。

2. 当事物1去删除pk=1且没有提交时, 事物2应该要能看到pk=1的记录(事物的隔离性)

过滤条件是聚簇索引:

1. delete – 将该记录标记为 delete-mark 

2. update – 将该记录 先物理delete (聚簇索引里主键相同的行最多只能有1),然后 insert (或者可以原地更新[in place update])(即使删除了,也可以通过undo进行还原)

过滤条件是二级索引:

1. delete – 将该记录标记为 delete-mark 

2. update – 将该记录标记为 delete-mark (索引列是columns + pk,即使是唯一索引更新也是和原来的不一样),然后 insert 

为什么没有insert

1. insert操作是不需要异步去purge,因为insert的记录之前是不存在的;

2.不存在记录(未提交)是没有别的事物能引用到的,所以insert以后,对应的undo可以直接删除,而不需要等待异步.

purge 总结:

1. delete-mark的记录最后会被purge线程回收,Purge会检测记录上是否有其他事物在引用undo,如果没有就可以删除。

2. innodb_purge_threads (5.6以后),可以设置的大一些,回收的速度会快一些。

innodb_purge_threads = 4

 

3.Insert-buffer thread

 负责insert buffer与辅助索引的合并操作。

 

4.redo-log thread

 负责重做日志缓冲的磁盘写入

 

5.Master thread(主线程)

master thread的线程优先级别最高。
后台进程Master thread 里面有两种循环,再循环内可以调用其他线程进行相关的操作。

其内部几个循环(loop)组成:主循环(loop),后台循环(background loop),刷新循环(flush loop),暂停循环(suspend loop)。主循环有1s循环和10s循环. 1s循环即循环执行一次就sleep 1s后又执行一次又sleep 1 s.

每秒一次的操作包括 :

1.日志缓冲刷新到磁盘, 即使事务没有提交(commit).

注意即使事务没有提交操作, innodb 重做日志缓存仍然会刷新到重做日志文件, 所以就算很大的事务操作的commit没有想象中那么慢.  

2.合并插入缓冲(可能),合并插入缓冲不一定每秒都执行, innodb引擎会判断当前1秒内发生的IO次数是否小于5, 如果小于5.则合并插入缓冲.

3. 最多刷新100 innodb缓冲池中的脏页到磁盘(可能),innodb存储引擎通过判断当前缓冲池中脏页的比例()是否超过配置文件中innodb_max_dirty_pages_pct这个参数的值.如果超过了这个阀值 ,innodb存储引擎则认为需要做磁盘同步操作,刷新100个脏页到磁盘.

4. 如果当前用户没有活动, 切换到 background thread (可能)

10秒执行的操作 :

1 .刷新100个脏页到磁盘 (总是)

2. 合并最多5个插入缓冲(总是)

3. 将日志缓冲刷新到磁盘(总是)

4. 删除无用的Undo(总是)

5. 刷新100个或者10个脏页到磁盘(总是)

10秒的循环操作中. innodb存储引擎首先判断过去10秒内的磁盘IO操作是否小于200, 如果小于,则将100个脏页刷新到磁盘.  然后合并 (最多5)插入缓冲, 然后将重做日志缓冲刷新到日志文件.然后,innodb存储引擎会执行一次full purge. 既删除无用的undo. 对表(磁盘)进行update, delete这类操作时,原先被标记为删除,但是因为一致性读(consistent read)的关系, 需要保留这些行版本的信息. 但是在full purge 过程中, innodb存储引擎会判断当前事务中已被删除的行是否可以在表(磁盘)中删除,如果可以,则立刻删除.  innodb在执行full purge操作时,每次最多尝试回收20undo page. 最后innodb存储引擎会判断缓冲池中脏页的比例,  如果超过70%, 则刷新100个脏页到磁盘, 如果脏页比例小于70%,则是刷新10%的脏页到磁盘

background loop :若当前没有用户活动或者数据库关闭(shutdown),就会切换到这个循环. background loop 会执行以下操作.

1 .删除无用的 undo (总是)

2. 合并20个插入缓冲页(总是)

3. 跳回到主循环(总是)

4. 不断刷新到100个脏页直到符合条件(可能, 跳转到flush loop 中完成)

flush loop 中也没有什么事情可以做了, innodb存储引擎会切换到suspend_loop. master_thread挂起, 等待事件发生.若用在mysql中启用了innodb存储引擎,但没有创建innodb, master thread总是处于挂起状态。

查看后台线程:

mysql> Show engine innodb status\G;

srv_master_thread loops: 56 1_second, 56 sleeps, 5 10_second, 6 background, 6 flush

srv_master_thread log flush and writes: 56

其中 srv_master_thread loops: 56 表示主循环进行了,56. 56 sleeps 表示挂起56, 5 10_second 表示10秒的循环执行了5. background loop执行6, flush loop执行6 如果 srv_master_thread loops sleeps 存在较大差距,则表明当前服务器可能很比较繁忙 , 因为innodb在其内部进行了优化, 在压力大的情况下,1秒循环并不是每次都sleep 。

 

6. IO有关参数

 innodb_io_capacity(落脏个数) . innodb_write_io_threads(写IO) .innodb_read_io_threads(读IO)     innodb_page_cleaners(刷脏频次)


  1. 落盘脏页个数参数(
innodb_io_capacity)

参数 :innodb_io_capacity :数据库落盘脏页个数 ,配置压力和磁盘的性能相关,如果过大,IO能力不足,则出现卡顿。

innodb_io_capacity默认是200,单位是页,该参数的设置大小取决于硬盘的IOPS,即每秒的输入输出量(或读写次数)。

可以动态调整参数:set global innodb_io_capacity=2000;

查看 innodb_io_capacity值: show variables like '%innodb_io_cap%';

配置建议如下: 

innodb_io_capacity           磁盘配置

200                    单盘SAS/SATA

2000                    SAS*12  RAID10

5000                    SSD

20000                   FUSION-IO

建议:尽量不要超过20000.

       

   2. IO读写参数(innodb_write_io_threads,innodb_read_io_threads

参数innodb_write_io_threads和innodb_read_io_threads 分别负责数据块的写入和读取,默认是4,高并发可设置为8.

  

       
      3.刷新lru list flush list的参数(innodb_page_cleaners
 MySQL5.6中,开启了一个独立的page cleaner线程来进刷lru list flush list。默认每秒运次1.MySQL5.7 可设置多个page cleaner线程提高脏页刷新效率 ;

15.6版本以前,脏页的清理工作交由master线程的;

2Page cleaner thread5.6.2引入的一个新线程(单线程),从master线程中卸下buffer pool刷脏页的工作独立出来的线程(默认是启一个线程)

35.7开始支持多线程刷脏页;

show global status like '%Innodb_buffer_pool_wait_free%';

如果值很大,则需要增加innodb_page_cleaners值,同时增加写线程。