InnoDB是如今使用的最多的储存引擎了吧。来看看它的特色:node
ACID事务mysql
行锁算法
MVCCsql
外键数据库
一致性非锁定读缓存
不支持全文索引数据结构
InnoDB的体系架构架构
主要是由内存块组成的内存池。oop
内存池的主要工做性能
1.维护内部数据结构
2.缓存重作日志
3.缓存磁盘上的数据,数据进入内存以前就存储在这里
后台线程负责刷新内存池,保证内存池中的缓存数据是最新的。
还有,将已经修改的数据存储到磁盘中。
后台线程
默认状况下,InnoDB有7个线程:4个IO线程、1个master 线程、1个错误监控线程、一个锁监控线程。
4个IO线程分别是:
insert buffer thread
log thread
read thread
write thread
在Linux系统中,IO线程的数量是不能调整的,可是在插件版的InnoDB中,read和write线程增长到了4个,
而且配置文件中没有innodb_file_io_threads这个参数。
-------- FILE I/O -------- I/O thread 0 state: waiting for completed aio requests (insert buffer thread) I/O thread 1 state: waiting for completed aio requests (log thread) I/O thread 2 state: waiting for completed aio requests (read thread) I/O thread 3 state: waiting for completed aio requests (read thread) I/O thread 4 state: waiting for completed aio requests (read thread) I/O thread 5 state: waiting for completed aio requests (read thread) I/O thread 6 state: waiting for completed aio requests (write thread) I/O thread 7 state: waiting for completed aio requests (write thread) I/O thread 8 state: waiting for completed aio requests (write thread) I/O thread 9 state: waiting for completed aio requests (write thread)
参数换成了innodb_read_io_threads和innodb_write_io_threads
mysql> show variables like 'innodb_version'\G; *************************** 1. row *************************** Variable_name: innodb_version Value: 5.6.36
1 row in set (0.00 sec) ERROR: No query specified mysql> show variables like 'innodb_%io_threads'\G; *************************** 1. row *************************** Variable_name: innodb_read_io_threads Value: 4
*************************** 2. row *************************** Variable_name: innodb_write_io_threads Value: 4
2 rows in set (0.00 sec)
内存
InnoDB引擎的内存由如下几部分组成:
缓冲池
mysql> show variables like 'innodb_buffer_pool_size'\G; *************************** 1. row *************************** Variable_name: innodb_buffer_pool_size Value: 134217728
1 row in set (0.00 sec)
重作日志缓冲池
mysql> show variables like 'innodb_log_buffer_size'\G; *************************** 1. row *************************** Variable_name: innodb_log_buffer_size Value: 8388608
1 row in set (0.00 sec)
额外的内存池
mysql> show variables like 'innodb_additional_mem_pool_size'\G; *************************** 1. row *************************** Variable_name: innodb_additional_mem_pool_size Value: 8388608
1 row in set (0.00 sec)
缓冲池占用的内存最大,用来缓存数据。
存储引擎工做方式:
将数据库文件按页(16K)读取到缓冲池中,而后按照最少使用(LRU)算法来保留缓冲池中的数据。
若是数据须要修改,优先修改缓冲池中的数据,修改后的页叫作脏页。
最后后台线程将脏页刷新到文件中。
mysql> show engine innodb status\G;
每一个帧为16K,因此缓冲池大小为8192*16/1024=128M。
Free buffers 当前空闲的缓冲帧数量。
Database pages 已经使用的缓冲帧
Modified db pages 脏页的数量
从上面的数据能够看出,缓冲池还剩下5.5%左右可使用。数据库压力比较大。
Per second averages calculated from the last 30 seconds
该命令显示的是过去30秒的状态,并不是最新的状态。
数据页的类型
索引页
数据页
undo页
插入缓冲(insert buffer)
自适应哈希索引(adaptive hash index)
InnoDB存储的锁信息(lock info)
数据字典信息(data dictionary)
等
日志缓冲将日志文件先放入缓冲区,而后刷新到重作日志。通常每秒就会将重作日志缓冲刷新到日志文件,日志缓冲的值不须要设置很大,大于每秒的事务量便可。
InnoDB引擎管理内存的方式叫作内存堆(heap)
在对某些数据结构自己进行内存分配时,首先从额外内存池分配,不够用就从缓冲池分配。
InnoDB实例的缓冲池中,缓冲帧对应的缓冲控制对象所需的内存也是从额外内存池分配的,
因此当缓冲池很大时,额外内存池的大小也要增长。
master thread
InnoDB引擎的主要工做都是在master thread由完成的。
master thread线程的优先级最高,经过分析其源代码能够知道,其内部由几个循环构成:
主循环(loop)
后台循环
暂停循环
刷新循环
master thread基本就是在这几个循环之间来回切换。
主循环(loop)
大部分操做都在此循环中完成,分为2大部分:每秒钟的操做和每10秒的操做
从代码中能够看出,是可能有延迟的。
每一秒的操做包括:
重作日志缓冲刷新到磁盘,即便这个事务尚未提交(老是)。
合并插入缓冲(可能)。
最多刷新100个InnoDB缓冲池中的脏页到磁盘(可能)。
若是当前没有用户活动,切换到后台循环(可能)。
即便事务没有提交,重作日志缓冲每秒也会被刷新到磁盘中的重作日志文件,这也是为何再大的事务提交的时间也很快。
合并插入缓冲并非每秒都发生。InnoDB引擎会判断一秒内发生的IO次数是够小于5次,若是小于5次,InnoDB认为IO压力很小,
就会执行插入缓冲合并。
一样,最多刷新100个脏页也不是必定发生。InnoDB会判断当前缓冲区脏页的比例是否超过了配置文件中innodb_max_dirty_pages_pct
参数(默认90%),若是超过了该值,就会刷新100个脏页到磁盘中。
接着来看每10秒的操做:
刷新100个脏页到磁盘(可能)。
合并至多5个插入缓冲(老是)。
将日志缓冲刷新到磁盘(老是)。
删除无效的重作页(老是)。
刷新100个或者10个脏页到磁盘(老是)。
产生一个检查点(老是)。
以上过程当中,InnoDB首先会判断过去10秒内,IO操做是否超过200次,
若是没有,将会把100个脏页刷新到磁盘。
以后,会合并插入缓冲。
以后,会将日志缓冲刷新到磁盘。
而后,删除无用的Undo页。
在执行update或者delete操做时,由于一致性读的关系,这些行的版本信息会被保留,
在进行Undo时,会去判断这些被删除的行是否能够删除
若是能够,当即删除。经过源代码能够知道,最多一次删除20个Undo页
而后,InnoDB回去判断缓冲池中脏页的比例,若是大于70%,则刷新100个脏页,不然,刷新10个脏页
最后,InnoDB会产生一个检查点,在此刻,InnoDB会将最老日志序列号(oldest LSN)的页写入磁盘。
接着来看后台循环
若是数据库没有活动,数据库空闲或者数据库关闭时,就会切换到这个模式。
这个循环会执行的操做:
删除无用的Undo页(老是)。
合并20个插入缓冲(老是)。
跳回到主循环 (老是)。
不断刷新100个页,知道符号条件(可能,跳转到flush loop中完成)
若是刷新循环没有什么活动,会切换到暂停循环,将master thread挂起。
若是启用了InnoDB引擎,却没有任何基于InnoDB的表,就是处于这个状态。
master thread的潜在问题
从上面的知识能够知道,源代码对IO作了限制。每秒最大刷新100个脏页或者刷新20个插入缓冲。
这个可能在某些程序中会致使master thread忙不过来
因此在InnoDB Plugin版本中加入了innodb_io_capacity参数,
用来表示磁盘IO吞吐量
mysql> show variables like 'innodb_io%'\G; *************************** 1. row *************************** Variable_name: innodb_io_capacity Value: 200
规则以下:
在合并插入缓冲时,数量为该值的5%
在刷新脏页时,数量为该值
若是使用了SSD和进行了Raid操做,能够将该值设置的高点。
另外一个问题是参数innodb_max_dirty_pages_pct,在mysql5.1(包括此版本),默认值为90%,
意味着脏页占缓冲池的90%,这个太大了!在InnoDB Plugin版本,该值被调整为了75%,
因此能够兼顾脏页刷新频率和磁盘IO。
InnoDB Plugin的另外一个参数是innodb_adaptive_flushing(自适应的刷新),该值影响每秒脏页的数量
mysql> show variables like 'innodb_adaptive_%'\G; *************************** 1. row *************************** Variable_name: innodb_adaptive_flushing Value: ON
这个参数会致使,当脏页在缓冲池的比例小于innodb_max_dirty_pages_pct时,也会刷新必定数量的脏页。
因此,最好使用InnoDB Plugin版本,对数据库的性能会有提高。
关键特性
InnoDB的关键特性还包括插入缓冲,2次写,自适应哈希索引。
插入缓冲
咱们知道,主键是行的惟一标识符,在表中,行的插入顺序是按照主键递增的
插入缓冲的使用要知足2个条件
索引是辅助索引
索引不是惟一的
2次写
这个能够保证数据的可靠性。
架构
当脏页刷新时,并非直接将其写入磁盘,而是先将其写入内存中的doublewrite buffer。
每次写入1M到共享表空间的磁盘中。这样若是数据库崩溃了,能够在共享表空间找到页的副本,
在应用重作日志来恢复。
自适应哈希索引
哈希是一种快速的查找方法。
经常使用语join操做
InnoDB引擎会监控表上的索引查找,若是观察到创建哈希索引会带来速度的提高,
就会创建哈希索引,这就是自适应哈希索引。
启动自适应哈希索引,能够带来读写性能2倍的提升;
能够带来辅助索引性能5倍的提升;
------------------------------------- INSERT BUFFER AND ADAPTIVE HASH INDEX ------------------------------------- Ibuf: size 1, free list len 0, seg size 2, 0 merges merged operations: insert 0, delete mark 0, delete 0 discarded operations: insert 0, delete mark 0, delete 0 Hash table size 276707, node heap has 402 buffer(s) 0.00 hash searches/s, 0.00 non-hash searches/s
默认开启
*************************** 3. row *************************** Variable_name: innodb_adaptive_hash_index Value: ON
启动、关闭和恢复
innodb_fast_shutdown参数影响InnoDB引擎的行为,默认为1
mysql> show variables like 'innodb_fast_shutdown'\G; *************************** 1. row *************************** Variable_name: innodb_fast_shutdown Value: 1 1 row in set (0.00 sec)
0 表示关闭数据库时,须要完成全部的full purge和merge insert buffer操做
若是在升级InnoDB Plugin,能够将该值设置为0
2 表示不完成full purge和merge insert buffer操做,也不将缓冲池中的数据脏页写会磁盘,而是写在日志。
innodb_force_recovery参数影响引擎的恢复状况,默认值为0
mysql> show variables like 'innodb_force_recovery'\G; *************************** 1. row *************************** Variable_name: innodb_force_recovery Value: 0 1 row in set (0.00 sec)