InnoDB引擎主要包含几个重要部分:
1、内存池
1.1 缓冲池
InnoDB将记录按页的形式进行管理,对于页的修改先修改缓冲池中的页,后以一定频率进行刷新到磁盘中(checkpoint)。在数据库的页读取操作时,将也缓存到缓冲池中,下一次如读取相同的页,则无需从磁盘中加载。缓存池大小通过innodb_buffer_pool_size配置。
三张链表的作用就是为了维护数据页 1) Free List: 维护空闲数据页,在数据库刚启动时,buffer pool中的数据页是空闲的,mysql会将这些空闲的数据 页添加到一个链表中,即Free List; 2) LRU List: mysql根据LRU算法(最近最少使用算法),对内存中的已经使用的数据页进行排序,添加到一个链表中, 即LRU链表,将数据页分为热端和冷端;innodb在LRU链表中加入mid_point位置,最新读取的页面, 并不是放到列表的前端而是放入到mid_point位置,这样可以防止热端数据被新加载的大量数据替换出 LRU链表;
midpoint指向的page及之后直到end的page,都被称为”old page”或者“old list",midpoint之前到start的所有page,被称为”young page”或者”young list“。当LRU有新数据需要加载的时候,会首先从midpoint位置开始加载,然后当插入old list中的数据页使用的频率高过一定值,会调入young list中。
3) Flush List: 存放有buffer pool当中的所有脏页,并按照一定的算法排序,按照数据页中记录的最早修改时间为依据对对数据页排序,修改时间最早的放在链首,如果需要刷脏,优先链首。
Flush List节点一定属于LRU list 节点,而于LRU list 节点不一定属于Flush List。
相关参数
innodb_max_dirty_pages_pct 默认75% LRU内的脏页如果超过75%,强制性的刷脏
innodb_old_blocks_pct 确定modpoint位置, 默认37
innodb_old_blocks_time 表示页读入mid位置后需要等待多久才会被加入到LRU列表的热端
1.3 mysql5.7新特性-buffer pool数据预热 数据库刚启动时,buffer pool中都是空数据页,没有所谓的热数据,随着一段时间的使用,热数据逐渐凸显出来,在这种情况下,就意味着数据库刚启动时性能是比较差的。为了解决这个问题提出了buffer pool数据预热。实现方法:就是在数据库实例关闭时,将buffer pool中一定比例的热数据保存在硬盘中,用于持久化,当数据库实例启动时,可以从磁盘中直接加载热数据到buffer pool,能在一定程度上避免上述提到的启动数据库性能较差的问题。 将热数据保存在某个文件中---ib_buffer_pool 用于存放热数据,如果使用数据预热的功能,需要使用如下参数: innodb_buffer_pool_load_at_startup=1 innodb_buffer_pool_dump_at_shutdown=1 innodb_buffer_pool_dump_pct=40 innodb_buffer_pool_dump_now=off innodb_buffer_pool_load_now=off innodb_buffer_pool_filename=ib_buffer_pool innodb_buffer_pool_dump_pct=40 建议使用40.这个参数可调更大的备份比,意味着要备份和加载更多的热数据,关闭mysql实例和启动mysql实例表现变差,但是启动后,表现更高。
1.4 redo log 在事务中进行了数据更新操作,实际上改变的有数据页,同时在修改数据页时,会产生相应的redo log日志信息,记录数据页中数据变化的偏移量,将该redo log暂时存放在内存中的redo log buffer(重做日志缓存区)中,当我们执行commit操作时,mysql会立即将redo log buffer中记录的相关redo log进行落盘操作,存放在硬盘上的redo log file中。 redo log的落盘机制? 1)、通过参数innodb_flush_log_at_trx_commit控制redo log落盘,其值有三种: 0:redo log每隔1s落盘一次,redo log的落盘就和事务没有关系了,不会再有commit的时候落盘; 1:每次commit,redo log落盘; 2:当会话执行commit操作时,redo log会立即从redo log buffer中刷新到OS cache中;在OS cache中 redo log以每秒一次的频率刷新到磁盘。 2)、当redo log buffer空间到了1/2,redo log落盘; 3)、mysql 内部存在1s 10s循环,促使redo log落盘; 相关参数: innodb_log_buffer_size --》 redo log buffer的大小 innodb_log_file_size --》 redo 日志文件的大小 innodb_log_files_in_group --》在一个redo log file group中有几个redo log file innodb_flush_log_at_trx_commit --》 控制redo log落盘 1.5 undo 日志 undo日志作用: rollback 和 MVCC 多版本控制 5.6版本开始,undo log file从ibdata1文件中独立出来;从5.7版本新特性,加入了参数,控制undo log file的大小,一旦发现undo log file暴增,就会对undo log file进行truncate,一旦发现undo log file 大小超过了某个阈值,就会截断操作。 相关参数: innodb_undo_logs = 128 #must >=35.default 128 innodb_undo_tablespaces = 3 #must >=2 innodb_undo_log_truncate = 1 开启在线回收undo表空间 innodb_max_undo_log_size = 1000M回收undo表空间的最大值,超过1G之后,可以出发undo truncate innodb_purge_rseg_truncate_frequency = 128 1.6 脏页落盘机制checkpoint 1) 检查点解决的问题: - 缩短数据库恢复时间 - 缓冲池不够用时,刷新脏页到磁盘 - 重做日志不够用时,刷新脏页 2) checkpoint分为两种: fuzzy checkpoint 模糊检查点---》当数据库触发了模糊检查点的时候,会进行部分刷脏; 触发点:MYSQL检测到LRU链表中没有足够的clean page;mysql 1s 10s循环操作;redo log不可用时; sharp checkpoint 清晰检查点--》当数据库触发了清晰检查点(全量检查点),会进行全部刷脏,将buffer pool中的所有脏页 刷新到硬盘上。 触发点: 正常关闭数据库 2、后台进程 1) master thread: 核心线程,维持数据库内部重要的两个循环 1s 10s 2) IO thread: IO 线程 input 输入 output 输出 ---》就是硬盘和内存的交互存在IO线程 主要包含:read thread(加载数据到buffer pool) write thread(刷脏) IO线程往往有很多,默认情况下,IO线程各4个,即read thread和write thread各4个,可设置为8,参照逻 辑cpu数而定。--》innodb_read_io_thread 和innodb_write_io_thread 3) log thread: 负责redo log 落盘的线程; 4) insert buffer thread: 负责insert buffer与辅助索引的合并操作 5) purge thread: 负责回收被标记为delete-mark的行记录空间以及不再被其他事务引用的undo 日志; 6) page clean thread: 负责脏页落盘,是从master thread分离出来的,专门负责递交脏页给write thread进行脏页落地;
3、InnoDB的工作特性
3.1 insert buffer--->5.5以后改名为change buffer
若插入按照聚集索引primary key插入,页中的行记录按照primary存放,一般情况下不需要读取另一个页记录,插入速度很快(如果使用UUID或者指定的ID插入而非自增类型则可能导致非连续插入导致性能下降,由B+树特性决定)。如果按照非聚集索引插入就很有可能存在大量的离散插入,insert buffer对于非聚集索引的插入和更新操作进行一定频率的合并操作,再merge到真正的索引页中。使用insert buffer需满足条件:
(1)索引为辅助索引。
(2)索引非唯一。(唯一索引需要从查找索引页中的唯一性,可能导致离散读取)
3.2 double write
Doubel write保证了页的可靠性,Redo log是记录对页(16K)的物理操作,若innodb将页写回表时写了一部分(如4K)出现宕机,则物理页将会损坏无法通过redolog恢复。所以在apply重做日志前,将缓冲池中的脏页通过memcpy到doublewrite buffer中,再将doublewrite buffer页分两次每次1MB刷入共享表空间的磁盘文件中(磁盘连续,开销较小),完成doublewrite buffer的页写入后再写入各个表空间的表中
3.3 adaptive hash index
Innodb根据访问频率对热点页建立哈希索引,AHI的要求是对页面的访问模式必须一样,如连续使用where a='xxx' 访问了100次。建立热点哈希后读取速度可能能提升两倍,辅助索引连接性能提升5倍。
通过show engine innodb status\G;查看hash searches/s, 表示使用自适应哈希,对于范围查找则不能使用 标签:log,buffer,undo,innodb,MySQL,InnoDB,redo,pool,体系结构 From: https://www.cnblogs.com/harda/p/16995868.html