第一部分:线程

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. VS2010命令行编译C#和VC项目

    VS2010命令行编译C#和VC项目 VS2010命令行编译C#和VC项目 根据需要动态创建数据库字段后,需要动态创建或者调整页面,那就需要编译这些页面和后台文件.因此使用命令行编译将会非常方便,对于 ...

  2. C,C++宏中#与##的讲解[转]

    MoreWindows 专注于Windows编程 C,C++宏中#与##的讲解 文中__FILE__与示例1可以参见<使用ANSI C and Microsoft C++中常用的预定义宏> ...

  3. SqlSever2005 一千万条以上记录分页数据库优化经验总结

    http://www.cnblogs.com/jirigala/archive/2010/11/03/1868011.html 待测试???

  4. 通知(Notification) 、 应用间通信(一)

    1 使用通知中心发送消息 1.1 问题 当一个对象需要向多个接受者发送消息的,或者不用知道消息的接收者是谁,就可以使用IOS提供的NSNotificationCenter通知中心,本案例使NSNoti ...

  5. 云数据库 Bmob

    /**************************************************************************************** * 云数据库 Bmo ...

  6. JS基础知识(数组)

    1,数组 var colors = new Array(); var colors = new Array(20); var colors = new Array(“red”, “blue”, “gr ...

  7. python 的一些小技巧

    赋值: a, b, c = 'xixi', 'haha', 'hehe' 连接字典: >>> s = {1:'a', 2:'b', 3:'c'} >>> s.key ...

  8. andorid中Html.fromHtml方法

    在android中,有一个容易遗忘的Html.fromhtml方法,意思是可以将比如文本框中的字符串进行HTML格式化,支持的还是很多的, 但要注意的是要在string.xml中用<!--cda ...

  9. 六个超大规模Hadoop(前景)

    http://cloud.zol.com.cn/441/4415033_all.html 希望自己可以尽快把Hadoop学好

  10. Codeforces Round #368 (Div. 2)A B C 水 图 数学

    A. Brain's Photos time limit per test 2 seconds memory limit per test 256 megabytes input standard i ...