第一部分:线程

Innodb是一个多线程的,各个线程负责不同的任务。主要的线程有:Master Thread、IO Thread、Purge Thread、Page Cleaner Thread

一,Master Thread :刷写数据、回收undo、回收脏页、合并插入缓冲

具有最高的优先级别,内部有多个循环(loop)组成:主循环(loop)、后台循环(background loop)、刷新循环(flush loop)、暂停循环(suspend loop),根据数据库的运行情况会在这些循环中切换。

该线程主要负责刷写数据,包括缓冲池的数据异步刷写到磁盘,脏页的刷写、合并插入缓冲、UNDO页的回收等。在主循环(loop)中有2大部分的操作:每1秒和每10秒的操作。

build-in Innodb

每一秒的操作:

1)日志缓冲刷写到磁盘,即使这个事务还没有提交(总是)。这解释了再大的事务提交的时间也很短。

2)合并最多5个插入缓冲(可能)。先判断前1秒的IO次数是否小于5次,小于则进行合并插入缓冲的操作。

3)刷写100个脏页到磁盘(可能)。先判断缓冲池的比例是否超过了innodb_max_dirty_pages_pct的值,如果超过则刷写100个脏页到磁盘。

4)如果没有用户活动则切换后台循环线程。

每十秒的操作:

1)刷写100个脏页到磁盘(可能)。先判断前10秒的IO次数是否小于200,小于则刷写100个脏页到磁盘。

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

3)日志缓冲刷写到磁盘(总是)。

4)删除最多20个无用的UNDO页(总是)。

5)刷写100或10个脏页到磁盘(总是)。先判断缓冲池的脏页比例是否大于70%,大于则刷写100个脏页到磁盘,小于则刷写10个脏页到磁盘。

通过每一秒和每十秒的信息看出:Master Thread对IO的操作都有限制,影响到了存储引擎的性能,为了提高性能,在Plugin innodb上做了提升:

Plugin Innodb

参数:innodb_io_capacity 表示磁盘IO的吞吐量,控制Innodb checkpoint时的IO能力,默认是200。对于刷新到磁盘的数量,会按照该参数的百分比进行刷写,而不是固定100、10等限制的大小刷写。

如之前的:合并5个插入缓冲 变成 合并5%*innodb_io_capacity的插入缓冲;

刷写100个脏页   变成 合并 100%*innodb_io_capacity的脏页;

刷写10个脏页    变成 合并 10%*innodb_io_capacity的脏页;

如innodb_io_capacity设置为500,

则刷写100个脏页大小为:100*16/1024 = 1.5625M;按照innodb_io_capacity的大小设置则脏页大小为:500*16/1024 = 7.8125M。

接着看后台循环(background loop):没有用户活动,数据库空闲或则关闭时,就会切换到这个循环,该循环下做如下事情:

1)删除无用的UNDO页(总是)。

2)合并20个插入缓存(总是)。

3)跳回主循环。如果不空闲了则跳回主循环,否则跳到flush loop。

接着看刷新循环(flush loop):

1)不断刷写100个脏页到磁盘。先判断缓冲池里脏页比例是否大于innodb_max_dirty_pages_pct,大于则不断刷新只到小于为止。

flush loop 没有事可做,则切换到暂停循环(suspend loop),将Master Thread挂起,等待事件发生。若用户开启innodb 存储引擎,但是没用innodb表,则Master Thread总是挂起。

二,IO Thread :可以用参数innodb_read_io_threads和innodb_write_io_threads 来控制read和write。

Innodb存储引擎大量使用了AIO(异步IO),提高了磁盘的操作性能。IO Thread 主要负责这些异步IO的回调。built-innodb有4个IO Thread:write、read、insert buffer、log。

三:Purge Thread:回收UNDO。5.5之后的参数,从Master Thread独立出来

回收无用的UNDO页,在MySQL 5.5之前是在Master Thread中完成的。5.5之后,独立到了单独的线程中完成,减轻了Master Thread线程的工作。提升CPU的使用率和存储引擎的性能。

通过参数innodb_purge_threads 来开启,在5.5中只能也只有1可以设置。5.6可以设置大于1。另一个参数:innodb_purge_batch_size 来控制每次回收UNDO页的数量,在5.5之前默认是20(写死),5.5之后可以根据情况调整该参数。

四:Page Clean Thread:刷写脏页,5.6之后的参数,从Master Thread独立出来

5.6里开始支持,脏页的刷写线程。从Master Thread里面独立出来。减轻了Master Thread 的工作,和对用户查询的阻塞。进一步提高Innodb 存储引擎的性能和并发。

第二部分:内存

Innodb的内存数据对象包括:缓冲池即innodb_buffer_pool(数据页、索引页、插入缓冲、自适应哈希索引、锁信息、数据字典)、重做日志缓冲即redo
log
buffer(innodb_log_buffer_size)、额外内存池(innodb_additional_mem_pool_size)。5.5开始有多个缓冲池实例(innodb_buffer_pool_instances),根据哈希值进行分配,好处是减少了数据库内部的资源竞争,提高并发处理能力。只有配置BP大于1G的时候,多实例BP才能生效。默认为1。

一:缓冲池即innodb_buffer_pool     

Innodb Buffer Pool是缓存数据和索引的缓冲区,负责管理free list(初始化空闲页等),flush
list(缓冲池产生的脏页),LRU list(通过LRU算法管理页面交换的,LRU
List分为2块:LRU_new、LRU_old。LRU_old为链表长度的3/8。页读取先进入old,访问时候从old进入到new。)即数据库的缓冲池(BP)可以看成一个LRU列表,根据最近最少使用算法进行管理,最频繁使用的在顶端,最少使用的在末端。当不能存放读取到的新页时,最先释放末端的页,将新页存放到顶端。Innodb在该LRU算法上进行了改进,加了一个midpoint的位置,新读取到的页不是放到顶端,而是放到midpoint的位置。因为某些SQL会使老的LRU算法出现问题:全索引、全表、mysqldump等类似的扫描多个页甚至是全部页的一次性SQL,会让缓冲池中真正的热点数据被刷出,影响缓冲池的效率。

midpoint位置在LRU列表的5/8处,由参数innodb_old_blocks_pct控制。midpoint 之前的位置称为new(young)即活跃的热点数据,之后的位置称为old。该参数默认值为37(尾端开始的3/8处),要是热点数据很多,则可以设置该参数,如20(尾端开始的1/5处)。

另一个参数Innodb_old_blocks_time :等到该时间后,再读取该页则会进入到new端,有效的避免了对于上述SQL对BP的污染。默认是0,单位是毫秒。如设置为1000则表示:读到该页到midpoint的位置,要再等1秒之后读取该页才能进入new列表。而0则表示读取到该页则会直接被放入到new列表。

page made young:页从LRU的old列表加入到new列表。

page not made young:由于Innodb_old_blocks_time的设置(非0),导致页没有从LRU的old列表加入到new列表。

上面可以通过 show engine innodb status 查看到。

二:重做日志缓冲即Innodb_log_buffer_size(事务日志缓存)

      Innodb存储引擎首先将重做(事务)日志信息放入到这个缓冲区,再按照一定频率(innodb_flush_log_at_trx_commit)刷写到重做(事务)日志文件中。日志缓冲大小设置为每秒产生的事务量即可。因为上面提过了Master Thread线程会每秒刷写日志缓冲到日志文件。还有其他的情况也会刷写:如每次事务提交和重做日志缓冲空间小于1/2的时候,当redo log buffer不够大的时候,会产生等待。可以通过show global status like 'Innodb_log_waits' 查看redo log buffer的等待状态。

三:额外的内存池(innodb_additional_mem_pool_size)

对数据结构本身的内存分配,还有锁、等待以及LRU等信息。

      

第三部分:Checkpoint

事务提交时,先写重做日志,再修改页。满足日志先行的原则。这样即使刷写数据到磁盘发生宕机也可以通过redo log 进行恢复,符合ACID中的D:持久性。事务日志(redo log)还可以提高事务的提交(顺序IO)和崩溃时候的恢复。

Checkpoint技术的目的:

①缩短数据库的恢复时间。数据库宕机,不需要做所有的redo log,Checkpoint之前的页都已经刷写到磁盘,只需要对其之后的redo log 进行恢复。

②缓冲池(BP)不够,刷写脏页。当缓冲池不够,则根据LRU算法会溢出最近最少使用的页,若该页是脏页则需要强制执行Checkpoint进行刷写。

③重做日志(redo log)不可用,则刷写脏页。因为redo log 是循环使用的,当新的事务需要写到日志文件时,而日志文件里的事务还没有来得及应用,不能被新事务覆盖使用时,需要强制执行Checkpoint进行刷写,将缓冲池中的页刷写到重做日志的位置。

Checkpoint做的事情就是把缓冲池中的脏页刷写到磁盘。触发刷写的操作的时机有:

①数据库关闭,innodb_fast_shutdown(Innodb外部)

②Master Thread每秒/每10秒刷写(Innodb内部)

③Flush_LRU_LIST,LRU列表需要有100个页空闲给用户查询使用,若没有则会阻塞查询操作,会把LRU列表的末端移除,若为脏页则需要Checkpoint。

④redo log不可用,需要进行强制的刷写操作。未刷写的页:lsn - checkpoint 。如redo log为2G。

* 未刷写的页<75%*2G,不需要刷写

* 75%*2G<未刷写的页<90%*2G,需要刷写,直到满足未刷写的页<75%*2G

在5.6之前,③和④过程会阻塞用户查询,并等待脏页刷写完成为止。5.6后有专门的Page Cleaner Thread,不会阻塞。

⑤缓冲池中的脏页太多,超过了innodb_max_dirty_pages_pct的值,会进行刷写。

第四部分:Innodb关键特性

Innodb存储引擎的关键特性包括:插入缓存(Insert Buffer -> Change Buffer)、两次写(Double Write)、自适应哈希索引(Adaptive Hash Index)、异步IO(Async IO)、刷写邻居页(Flush Neighbor Page)

一,插入缓冲(Insert Buffer/Change Buffer):提升插入性能

InnoDB为了避免更新数据时更新索引损失太多性能,使用了这种称为Insert Buffer的方法来缓冲索引更新。

只对于非聚集索引(非唯一)的插入和更新有效,对于每一次的插入不是写到索引页中,而是先判断插入的非聚集索引页是否在缓冲池中,如果在则直接插入;若不在,则先放到Insert
Buffer 中,再按照一定的频率进行合并操作。这样通常能将多个插入合并到一个操作中,提升插入性能

按照Master Thread的调度规则来合并非唯一索引和索引页中的叶子结点,这样经常能减少更新索引的代价。使用插入缓冲的条件:

* 非聚集索引

* 非唯一

插入缓冲最大使用空间为1/2的缓冲池大小,不能调整大小,在plugin innodb中,升级成了Change Buffer。不仅对insert,对update、delete都有效。其参数是:

innodb_change_buffering,设置的值有:inserts、deletes、purges、changes(inserts和deletes)、all(默认)、none。

可以通过参数控制其使用的大小:

innodb_change_buffer_max_size,默认是25,即缓冲池的1/4。最大可设置为50。在5.6中被引入。

上面提过在一定频率下进行合并,那所谓的频率是什么条件?

1)辅助索引页被读取到缓冲池中。正常的select先检查Insert Buffer是否有该非聚集索引页存在,若有则合并插入。

2)辅助索引页没有可用空间。空间小于1/32页的大小,则会强制合并操作。

3)Master Thread 每秒和每10秒的合并操作。

二,两次写(DoubleWrite)

提高数据安全,当页写入失效时,先通过页的副本(共享表空间中)来还原,再通过redo log 来重做。由2部分组成,一部分是内存中double write buffer,2M大小;另一部分是磁盘上共享表空间的连续的128页,即2个区(extent),2M大小的doublewrite。

缓冲池刷写脏页时,并不是直接写磁盘,而是先写到内存中的DoubleWrite中,之后再通过DoubleWrite顺序的写到共享表空间的DoubleWrite中,最后刷写磁盘。这样意味这刷写数据都要多写一份,增加了IO。但DoubleWrite是顺序的,所以开销不大。相比之下,牺牲一点点开销来提升安全是很有必要的。
参数:

Innodb_dblwr_pages_written:写的页数

Innodb_dblwr_writes:写的次数

Innodb_dblwr_pages_written:Innodb_dblwr_writes 要是小于64:1则写压力不高。大于则表示压力高

Innodb_dblwr_pages_written和Innodb_buffer_pool_flushed (从缓冲池刷写到磁盘的页的数量)应该是一致的,因为缓冲池的刷写都会先存放到doublewirte中,即可以通过他们看出数据库的写入量。

参数skip_innodb_doublewrite 禁止双写。双写缓存的更多信息可以看关于innodb中两次写的探索

三,自适应哈希索引:提高查询效率

四,异步IO:提高磁盘的操作性能

5.5之前,是通过代码实现的(不能修改),5.5之后新增了参数:innodb_use_native_aio来控制是否启用,默认值得为ON。启用恢复数据提升75%。

五,刷新邻接页

      工作原理:刷写一个脏页时,会检测该页所在的区(extent:64页,1M)的其他页是否也有脏页,有则一起刷写。5.6可以通过参数来控制是否刷写:

innodb_flush_neighbors,机械磁盘建议开启,固态硬盘建议设置为0,即关闭。

Innodb 存储引擎(转)的更多相关文章

  1. MySQL数据库和InnoDB存储引擎文件

    参数文件 当MySQL示例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数,这些参数通常定义了某种内存结构有多大等.在默认情况下,MySQL实例会按照一定 ...

  2. 在MySQL的InnoDB存储引擎中count(*)函数的优化

    写这篇文章之前已经看过了很多数据库方面的优化内容,大部分都是加索引.使用事务.要什么select什么等等.然而,只是停留在阅读的层面上,很少有实践,因为没有遇到真实的项目,一切都是纸上谈兵.实践是检验 ...

  3. MySQL InnoDB存储引擎

    200 ? "200px" : this.width)!important;} --> 介绍 本篇文章是对Innodb存储引擎的概念进行一个整体的概括,innodb存储引擎的 ...

  4. [MySQL Reference Manual]14 InnoDB存储引擎

    14 InnoDB存储引擎 14 InnoDB存储引擎 14.1 InnoDB说明 14.1.1 InnoDB作为默认存储引擎 14.1.1.1 存储引擎的趋势 14.1.1.2 InnoDB变成默认 ...

  5. myisam、innodb存储引擎比较

    MYSQL表类型(存储引擎) 1.概述 MySQL数据库其中一个特性是它的存储引擎是插件式的.用户可以根据应用需要选择存储引擎.Mysql默认支持多种存储引擎,以适用各种不同的应用需要.默认情况下,创 ...

  6. Galera集群server.cnf参数调整--Innodb存储引擎内存相关参数(一)

    在innodb引擎中,内存的组成主要有三部分:缓冲池(buffer pool),重做日志缓存(redo log buffer),额外的内存池(additional memory pool).

  7. innodb 存储引擎特性

    使用独立表空间后,系统表空间存储什么内容呢?   1.innodb 数据字典信息   和存储引擎相关.   frm 是服务器的数据字典和存储引擎无关. 2. undo 回滚段.   可以单独存储.   ...

  8. MySQL内核:InnoDB存储引擎 卷1

    MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...

  9. mysql innodb存储引擎介绍

    innodb存储引擎1.存储:数据目录.有配置参数为“ innodb_data_home_dir ” .“ innodb_data_file_path ” 和 “innodb_log_group_ho ...

  10. MySQL:InnoDB存储引擎的B+树索引算法

    很早之前,就从学校的图书馆借了MySQL技术内幕,InnoDB存储引擎这本书,但一直草草阅读,做的笔记也有些凌乱,趁着现在大四了,课程稍微少了一点,整理一下笔记,按照专题写一些,加深一下印象,不枉读了 ...

随机推荐

  1. Magento中,调用静态块的几种方法

    在后台创建一个order_form静态块Block Title :Order FormIdentifier :order_formStatus :EnabledContent :自定义内容 1.如果要 ...

  2. iOS开发资源:几个类似Path 2.0侧滑菜单的效果实现

    IIViewDeckController/ViewDeck 类似 Path 2.0 的视图左右滑动的效果,可向左或者向右顺滑的滑动.支持ARC和non-ARC,默认ARC. https://githu ...

  3. Howto add permanent static routes in Ubuntu

    Static routing is the term used to refer to the manual method used to set up routing. An administrat ...

  4. MySQL 获得当前日期时间(以及时间的转换)

    1.1 获得当前日期+时间(date + time)函数:now() 除了 now() 函数能获得当前的日期时间外,MySQL 中还有下面的函数: current_timestamp()   curr ...

  5. 服务调用方案(Spring Http Invoker) - 我们到底能走多远系列(40)

    我们到底能走多远系列(40) 扯淡:  判断是否加可以效力于这家公司,一个很好的判断是,接触下这公司工作几年的员工,了解下生活工作状态,这就是你几年后的状态,如果满意就可以考虑加入了. 主题: 场景: ...

  6. hdu 2665 Kth number

    划分树 /* HDU 2665 Kth number 划分树 */ #include<stdio.h> #include<iostream> #include<strin ...

  7. SSIS 组件点滴

    一 Sort组件 Sort组件是用来排序,我们在做join时也必须进行排序,排序的键值作为数据源关联的key 而在sort组件中有一个选项“Remove Rows with duplicate sor ...

  8. java script 闭包

    闭包的概念真的是很绕,我就来点实际的代码. 当我用下面的代码的时候 发生了闭包,当执行onclick事件的时候,变量一直引用了外部函数的变量,结果i总是4 function newLoad() { / ...

  9. python学习笔记 - assert用法

    [转自]http://blog.sina.com.cn/s/blog_76e94d210100vz37.html   1.assert语句用来声明某个条件是真的. 2.如果你非常确信某个你使用的列表中 ...

  10. 使用Dnsmasq搭建本地dns服务器上网

    导读 搭建一个属于自己的本地DNS服务器很有必要,利用Dnsmasq来搭建一个属于自己的本地DNS服务器,享受更干净无污染.更智能快速和没有广告干扰的DNS解析服务. 一.Dnsmasq安装 安装并启 ...