第一部分:线程
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 存储引擎(转)的更多相关文章
-
MySQL数据库和InnoDB存储引擎文件
参数文件 当MySQL示例启动时,数据库会先去读一个配置参数文件,用来寻找数据库的各种文件所在位置以及指定某些初始化参数,这些参数通常定义了某种内存结构有多大等.在默认情况下,MySQL实例会按照一定 ...
-
在MySQL的InnoDB存储引擎中count(*)函数的优化
写这篇文章之前已经看过了很多数据库方面的优化内容,大部分都是加索引.使用事务.要什么select什么等等.然而,只是停留在阅读的层面上,很少有实践,因为没有遇到真实的项目,一切都是纸上谈兵.实践是检验 ...
-
MySQL InnoDB存储引擎
200 ? "200px" : this.width)!important;} --> 介绍 本篇文章是对Innodb存储引擎的概念进行一个整体的概括,innodb存储引擎的 ...
-
[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变成默认 ...
-
myisam、innodb存储引擎比较
MYSQL表类型(存储引擎) 1.概述 MySQL数据库其中一个特性是它的存储引擎是插件式的.用户可以根据应用需要选择存储引擎.Mysql默认支持多种存储引擎,以适用各种不同的应用需要.默认情况下,创 ...
-
Galera集群server.cnf参数调整--Innodb存储引擎内存相关参数(一)
在innodb引擎中,内存的组成主要有三部分:缓冲池(buffer pool),重做日志缓存(redo log buffer),额外的内存池(additional memory pool).
-
innodb 存储引擎特性
使用独立表空间后,系统表空间存储什么内容呢? 1.innodb 数据字典信息 和存储引擎相关. frm 是服务器的数据字典和存储引擎无关. 2. undo 回滚段. 可以单独存储. ...
-
MySQL内核:InnoDB存储引擎 卷1
MySQL内核:InnoDB存储引擎卷1(MySQL领域Oracle ACE专家力作,众多MySQL Oracle ACE力捧,深入MySQL数据库内核源码分析,InnoDB内核开发与优化必备宝典) ...
-
mysql innodb存储引擎介绍
innodb存储引擎1.存储:数据目录.有配置参数为“ innodb_data_home_dir ” .“ innodb_data_file_path ” 和 “innodb_log_group_ho ...
-
MySQL:InnoDB存储引擎的B+树索引算法
很早之前,就从学校的图书馆借了MySQL技术内幕,InnoDB存储引擎这本书,但一直草草阅读,做的笔记也有些凌乱,趁着现在大四了,课程稍微少了一点,整理一下笔记,按照专题写一些,加深一下印象,不枉读了 ...
随机推荐
-
nginx超时重发
最近一直遇到一个bug: 客户端会二次请求服务端,服务端多次调用remote服务. 特点是,这些请求都是模型切片相关的,耗时很长的请求,往往需要1分钟左右. 开始以为是客户端代码有问题,进行了二次请求 ...
- Eclipse cpp 开发 include路径
-
EF Code First 数据迁移命令
只需要开启程序管理控制台(Package Manager Console) 然后输入 Enable-Migrations -ContextTypeName youContextdb(你的数据库上下文 ...
-
Android 自学之日期DatePicker、时间TimePicker选择器
日期(DatePicker).时间(TimePicker)是两个比较易用的控件,他们都是从帧布局FrameLayout派生而出的:他们在FrameLayout的基础上提供了一些方法来获取当前用户所选择 ...
-
浙江大学PAT上机题解析之5-05. QQ帐户的申请与登陆
实现QQ新帐户申请和老帐户登陆的简化版功能.最大挑战是:据说现在的QQ号码已经有10位数了. 输入格式说明: 输入首先给出一个正整数N(<=105),随后给出N行指令.每行指令的格式为:“命令符 ...
-
C++构造函数初始化列表与赋值
C++中类的初始化操作一般有四个部分组成: 1.构造函数初始化列表 2.构造函数体内赋值 3.类外部初始化 4.类声明时直接赋值 对于内部数据类型(char,int,float...),构造函数初始化 ...
-
Openflow协议详解
http://www.h3c.com/cn/d_201811/1131080_30005_0.htm# 1 OpenFlow背景 转发和控制分离是SDN网络的本质特点之一 .在SDN网络架构中,控制平 ...
-
一篇入门 -- Git
一. Git 介绍 Git作为一款分布式的==版本控制==工具,作为一名程序员,是必须要掌握的. 最初由林纳斯·托瓦兹(Linus Torvalds)创作,于2005年以GPL发布.最初目的是为更好地 ...
-
转载 线程池之ThreadPool类与辅助线程 - <;第二篇>;
http://www.cnblogs.com/kissdodog/archive/2013/03/28/2986026.html 一.CLR线程池 管理线程开销最好的方式: 尽量少的创建线程并且能将线 ...
-
BZOJ.2938.[POI2000]病毒(AC自动机)
题目链接 \(Description\) 给n个模式串,问是否存在长度无限的主串,使得任何一个模式串都没有在主串中出现. \(Solution\) 先建AC自动机. 假设我们有了一个无限长的安全代码, ...