一、InnoDB体系架构
内部有多个内存块组成内存池,用于:
1.维护进程线程要访问的内部数据结构
2.缓存磁盘数据
3.重做日志缓冲
二、后台线程
1.Master Thread
缓冲池中数据刷新到磁盘,确保数据一致性
2.IO Thread
AIO处理写请求,IO thread 负责这些请求的回调处理
3.Purge Thread
当事务提交后,undolog可能不在需要,purge用于回收已使用并分配的undo页
4.Page Cleaner Thread
脏页的刷新工作从Master Thread中提取出来,1.2x引入
三、内存
1.缓冲池
对于数据库中页的修改,先修改缓冲池中的页,再按一定频率刷新到磁盘上,由Checkpoint机制触发。
innodb_buffer_pool_size
其中缓存数据页类型包括:索引页、数据页、undo页等
允许多个缓冲池实例,页根据hash分配到不同实例中,减少资源竞争
2.LRU List Free List Flush List
通过midpoint将最新访问的页放在LRU列表的midpoint位置,主要因为某些SQL操作会导致索引或数据的扫描,会访问较多甚至全部的页,但其中一些页并不是热点数据,若放在首部位置将可能把真正的热点数据从列表中移出。
数据库启动时所有页放在Free列表中,当需要从缓冲池中分页时先去Free List中查找,若有则加入LRU List中。
SHOW_ENGINE_INNODB_STATUS观察LRU与Free使用情况
Buffer pool hit rate 表示缓存的命中率,不应小于95%
unzip_LRU 将原本16KB页进行压缩,利用伙伴算法进行内存的分配
当LRU List中页被修改后,变为脏页,而Flush List中页即为脏页;LRU管理缓冲池中页的可用性,Flush则管理将页刷新到磁盘
Modified db pages脏页数量
3.重做日志缓冲
InnoDB将重做日志信息先放入此缓冲区,再按频率刷新到重做日志文件。innodb_log_buffer_size default 8M
1.Master Thread 每秒刷新
2.每个事务提交刷新
3.重做日志缓冲池剩余空间小于1/2时刷新
4.额外的内存池
对一些数据结构本身的内存进行分配需从额外内存池中申请,p31
四、Checkpoint
为避免将数据刷新到磁盘时宕机丢失数据,采用Write Ahead Log策略,即事务提交时先写redo log,再修改页。但存在两个前提:1.缓冲池可以缓存所有数据库数据;2.redo log可无限增大。且恢复时间可能较久。
Checkpoint主要解决:1.缩短数据库恢复时间;2.缓冲池不够用,将脏页刷新到磁盘;3.redo log不可用时刷新脏页。
通过LSN标记版本。
可分为1.Sharp Checkpoint,default,数据库关闭时将脏页刷新到磁盘;2.Fuzzy Checkpoint运行时刷新一部分脏页
主要有以下几种情况:
1.Master Thread Checkpoint
2.FLUSH_LRU_LIST 确保LRU中有约100个页可用
3.Async/Sync Flush redo log 不可用;确保redo log循环使用
4.Dirty Page too much
五、Master Thread
1.0x前
具有最高线程优先级,包含多种循环,根据数据库状态在多个循环间进行切换。
1.loop主循环分为每秒与每10秒
每秒包括:
1.日志缓冲刷新到磁盘,即使事务还没提交(总是);
2.合并插入缓冲(IO压力小时,次数<5);
3.至多刷新100个脏页到磁盘(脏页比例>90%);等
每10秒:
1.刷新100个脏页到磁盘(可能);
2.合并至多5个插入缓冲(总是);
3.将日志缓冲刷新到磁盘(总是);
4.删除无用的undo页(总是,full purge);
5.刷新100或10个脏页到磁盘(总是)。
2.background loop
数据库空闲或关闭时切换到此循环,执行:
1.删除无用undo页(总是);
2.合并20个插入缓冲(总是);
3.跳回主循环(总是);
4.不断刷新100个页直到符合条件(可能,跳转flush loop)。
1.2x前
1.0x中对IO存在限制。
引入innodb_io_capacity
1.2x
刷新脏页由Master Thread分离到Page Cleaner Thread
六、关键特性
1.插入缓冲
1.insert buffer:主键为聚集索引,记录插入时按照主键递增顺序,不需要磁盘随机读取。但是当使用其他非聚集索引时,且非唯一,此时进行插入时,数据页存放仍是按主键顺序,非聚集索引页子节点插入为离散,而随机读取导致插入操作性能下降。故引入insert buffer 先判断插入非聚集索引是否在缓冲池中,若在,直接插入,不在,则先放入insert buffer 中。然后再以一定频率和情况进行insert buffer和辅助索引页的merge,将多个插入合并到一个操作中,从而提高非聚集索引的插入性能。
2.change buffer
对DML操作进行缓冲
3.insert buffer内部实现
通过全局B+树对所有表的辅助索引进行insert buffer,非叶节点存放search key
4.merge insert buffer
1.辅助索引页被读取到缓冲池中;
2.insert buffer bitmap追踪该辅助索引页已无可用空间时;
3.Master Thread
2.两次写
doublewrite用于保证数据页可靠性
当innodb写入某个页到表的过程中发生宕机,导致页损坏,无法通过redo log进行恢复时,需要用该页的副本先进行还原,再进行redo ,即为doublewrite
doublewrite包括两个部分,内存中doublewrite buffer与共享表空间128个页,当脏页刷新时,通过memcpy将脏页先复制到内存buffer中,通过buffer分为两次,每次1M顺序的写入到共享表空间物理磁盘上,然后调用fsync,同步磁盘,整个过程为顺序写入。完成doublewrite页写入后,再将buffer中页写入各个表空间文件中,此时写入为离散的。
3.自适应hash索引
时间复杂度低,O(1),但是对页的连续访问模式必须一致,即查询条件一致,且以该模式访问100次
4.AIO
优势在于IO Merge
5.刷新邻近页
当刷新一个脏页时,会检测该页所在区,若有脏页则一起刷新,且可通过AIO将多个写入合并为一个IO操作