一:Innodb的版本区别介绍,可以简单了解下.
二:Innodb存储引擎概述.
第一个完整支持ACID事物的MySql存储引擎,特点是行锁设计,支持MVCC,支持外键,提供一致性非锁读。同时被设计用来最有效地利用以及使用内存和CPU.
三:Innodb体系结构
从图中可以看到.Innodb存储引擎中由多个内存块. 可以认为这些内存块组成了一个大的内存池,负责如下工作:
1.维护所有进程/线程,需要访问的多个内部数据结构。
2.缓存磁盘上的数据,方便快速读取,同时在对磁盘文件的数据修改之前在这里缓存
3.重做日志的缓存 等.
后台线程的主要作用是负责刷新内存池中的数据,保证缓冲池中的内存缓冲是最近的数据。此外将已修改的数据文件刷新到磁盘文件,同时保证在数据库发生异常的情况下Innodb能恢复到正常的情况。
3.1后台线程
Innodb是多线程模型,后台有多个线程,负责处理不同的任务.
3.1.1 Master Thread
Master Thread 是一个非常核心的后台线程,主要负责将缓冲池的数据异步刷新到磁盘.保证数据的一致性,包括脏页的刷新,合并插入缓冲(INSERT BUFFER),UNDO页的回收,
3.1.2 IO Thread
在Innodb存储引擎中大量使用了AIO(async IO)来处理写IO请求.这样可以极大提高数据库性能.而IO Thread的工作主要是负责这些IO请求的回调处理.
3.1.3Purge Thread
事物被提交后,其所使用的undolog可能不再需要.因此需要Purge Thread来回收已经使用并分配的Undo页.
3.1.4 Page Cleaner Thread
Page Cleaner Thread 的作用是将之前版本中脏页的刷新操作都放入到单独的线程中来完成.
3.2 内存
3.2.1 缓冲池
具体来看,缓冲池中常见的页的类型有:索引页,数据页,undo页,插入缓冲(insert buffer),自适应哈希索引(adaptive hash index),Innodb存储的锁信息(lock info),数据字典信息(data dictionary)
show variable like 'innodb_buffer_pool_size'; 查看缓冲池大小.
从mysql 5.6开始,可以在information_schema 数据库查看innodb_buffer_pool_stats表来查看缓冲池信息.比如: use information_schema; select pool_id,pool_size,free_buffers,database_pages from innodb_buffer_pool_stats;
3.2.2 LRU List,Free List和Flush List
LRU(latest recent use):即最近最少使用算法。将最频繁使用的页放在LRU的前端,最少使用的放在LRU的后端.这样当内存不足的时候,首先释放LRU的后端内容. Mysql 对这个进行了优化。每次读取到了新的页,不是放在LRU的首部,而是放在一个 midpoint点。一般是靠着LRU末端的3/8 地方。这样做的目的是防止某次大量查询结构,如果放在LRU首部,会将整个LRU的热点数据覆盖掉.从而影响缓冲池的效率。因为这次查询的大量数据可能不是热点数据.但是这个 优化的midpoint是可以改的。可以通过该语句进行查询:show variables like 'innodb_old_blocks_pct';
Free List:当数据库刚启动的时候,LRU列表是空的,此时页都存储在Free List中。当需要从缓冲池中分页时,首先看下Free List是否有空余的,如果有,就将该页从Free中删除,加入到LRU中。否则就根据LRU列表。淘汰LRU末端的页.当页从列表的old部分加入到new部分时,此时操作称为page made young:缓冲池的命中参数:hit_rate.一般不小于95%.否则考虑是否时全表扫描导致LRU列表被污染了。
Flush List:当LRU列表中的页被修改了之后,称该页为脏页,即缓冲池中的数据和磁盘中数据不一致.这时数据库会通过CHECKPOINT机制将脏页刷回磁盘。脏页既存在LRU列表中。也存在Flush List中。
3.3 重做日志缓冲
Innodb存储引擎首先将重做日志放入到缓存中. 然后按照一定的频率刷新到重做日志文件中.
因此缓冲池的大小不需要设置的过大。因为一般情况下每秒都会将缓冲池的刷新到日志文件中.重做日志会在下面几种情况下将日志缓冲刷新到日志文件:
1) Master Thread 每秒钟将重做日志文件刷新到重做日志
2)每个事物提交会将重做日志缓冲刷新到重做日志文件中
3)当重做日志缓冲池小于剩余空间的1/2.重做日志缓冲 刷新到重做日志文件中.
四:CheckPoint技术
CheckPoint 技术即将缓冲中的数据的某个点的数据 全部刷新到磁盘。记住不是刷新到日志文件。刷新到磁盘相当于提交了commit了。即使宕机了。重启即可.而如果只是刷新到了日志文件。宕机重启后还需要执行下日志文件.如果日志文件比较大。就会很耗时.
checkpoint解决如下问题:
1)缩短数据库恢复时间
2)缓冲池不够用时,将脏页刷新到磁盘
3)重做日志不可用时,刷新脏页
第一点上面已经解释了。第二点,当出现这种情况,强制刷新执行CheckPoint.将脏页刷新到磁盘。就可以将这块脏页重新使用。第三点.正常重做日志 不应该无限增大。当数据都已经刷新到了磁盘,这部分的重做日志文件就没有意义了。就可以重新被覆盖使用了。可以循环使用.
CheckPoint有两种:Sharp CheckPoint和 Fuzzy CheckPoint.前者将所有的脏页刷新到磁盘,后者只将部分的脏页刷新到磁盘。默认是第二种.第一种对系统的可以性有比较大的影响,在数据库关闭之前会执行Sharp CheckPoint。 那么在以下几种情况会执行 Fuzzy CheckPoint。
1)Master Thread CheckPoint 该线程每秒或者每十秒异步执行CheckPoint。
2) Flush_LRU_LIst CheckPoint 当缓冲池的内存不够,执行checkPoint。保证LRU有空闲列表使用
3)Async/Sync Flush CheckPoint 当重做日志不可使用的时候,执行checkPoint
4)Dirty Page too much checkPoint 从名称就可以看出,脏页太多。
checkPoint 的作用是将一部分修改操作执行在数据库中。这样日志文件,缓冲内存可以复用。
五:Innodb关键特性
1.Insert Buffer
对于非主键索引的插入。如果每次插入数据都是直接插入,由于非主键索引不是顺序的。所以比较耗性能.insert buffer 是针对非聚集索引.每次的更新和操作,不是直接作用于索引页,而是先判断该索引是否在缓冲池中.如果在,则直接插入,如果不在,则放入Insert Buffer对象中.然后 以一定的频率进行Insert Buffer对象合并操作,将多个更新修改操作合成一次操作.
2.两次写(double write)
两次写 保证了Innodb 存储引擎 数据页的可靠性. 比如 当发生数据库宕机后,可能Innodb存储引擎正在写入某个页到表中.而这个页只写了一部分,比如16KB的页,只写了前4KB.然后发生了宕机. 正常出现这个问题,是可以通过重做日志进行恢复物理操作.但是发生宕机,写数据的时候 这个页发生了损坏.用重做日志对这个页进行恢复就不行了.在 应用重做日志之前,需要有个这个页的副本,当写失效发生时,先通过副本还原该页.再进行重做日志操作. 这就两次写(double write)。将数据写入 double write页中是顺序写入。所以这个开销不是很大.
3.自适应哈希索引
自适应哈希索引 是 Innodb 存储引擎 发现对 某个表的访问方式是连续一致的。比如 总是 where a=xxx. 然后就会自动建立哈希索引. 即需要一定的条件触发。 我们可以通过通过参数进行启用或者禁用这个特性. innodb_adaptive_hash_index;
4.异步IO
当前的数据库系统都是采用异步IO(Asynchronous IO)的方式来处理磁盘操作. 异步IO 简单解释下,就是发送了一个IO操作,不需要等待这个IO结束,立马发送其他的IO请求操作。
5.刷新邻接页
就是准备刷新脏页到磁盘时,如果检测附件的其他页也是脏页,可以一次刷新. 但是现在硬盘性能提高。该特性可以忽略。
七:启动,关闭和恢复
在Mysql数据库关闭的时候。innodb_fast_shutdown参数默认值为1(可取值 0,1,2)
当为 0时。标识Innodb需要完成所有的full purge和 merge insert buffer.并将所有的脏页刷新到磁盘。这将耗费许多时间.在进行innodb升级的时候,需要调为0防止数据丢失.再关闭数据库
当为1.表示不需要完成 full purge和Merge insert buffer操作。但是缓存池的脏页还是会刷新到磁盘.
默认值为1.
当为2时,不进行full purge和merge insert buffer操作,同时也不进行缓存池的脏页刷新到磁盘操作.而是将日志写入到日志文件.下次启动的时候进行恢复操作.
在Mysql数据库启动的时候,innodb_force_recovery 默认值为0(取值0-6).代表当发生需要恢复时,进行所有的恢复操作。
当为1(SRV_FORCE_IGNORE_CORRUPT) 忽略检查到的currupt页
2(SRV_FORCE_NO_BACKGROUND)阻止 Mater Thread 线程的运行
3(SRV_FORCE_NO_TRX_UNDO)不进行回滚操作
4(SRV_FORCE_NO_IBUF_MERGE)不进行插入缓冲操作
5(SRV_FORCE_NO_UNDO_LOG_SCAN)不查看撤销日志。将未提交的日志视为已提交
6(SRV_FORCE_NO_LOG_REDO)不进行前回滚的操作.
这里主要是了解.
如果需要对MySQL Innodb 更详细的了解。 请查阅<<MySQL 技术内幕 Innodb存储引擎第二版>>