MySQL——InnoDB体系结构

 

 InnoDB引擎主要包含几个重要部分: 
1、内存池 
1.1 缓冲池 
InnoDB将记录按页的形式进行管理,对于页的修改先修改缓冲池中的页,后以一定频率进行刷新到磁盘中(checkpoint)。在数据库的页读取操作时,将也缓存到缓冲池中,下一次如读取相同的页,则无需从磁盘中加载。缓存池大小通过innodb_buffer_pool_size配置。 

从上图来看,主要包括索引页、数据页、undo页、insert buffer、adaptive hash index、数据字典等,其中索引页和数据页占用多数内存。
 
1.2 LRU List、Free List、Flush List 
 
三张链表的作用就是为了维护数据页
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, 表示使用自适应哈希,对于范围查找则不能使用
posted @ 2022-12-21 11:25  Harda  阅读(153)  评论(0编辑  收藏  举报