《MySQL技术内幕》读书笔记2--存储引擎

InnoDB存储引擎

1 概述

  • 从MySQL5.5开始InnoDB是默认的表存储引擎
  • 第一个完整支持ACID事务的MySQL存储引擎
  • 特点:行锁设计、支持MVCC、支持外键、一致性非锁定读、有效利用内存和CPU
  • InnoDB1.2.x增加了全文索引支持、在线索引添加

2 体系架构

2.1 内存池(多个内存块)

  • 维护进程线程需要访问的多个内部数据结构
  • 缓存磁盘数据,对磁盘文件的数据修改也在内存中缓存
  • 重做日志缓冲

2.2 后台线程

  • Master Thread:核心线程,负责将缓冲池中的数据异步刷新到磁盘,保证数据一致性,包括脏页、合并插入缓冲,UNDO页回收等
  • IO Thread:在存储引擎中大量使用AIO来处理写IO请求,IO Thread负责IO请求的回调;10个IO线程:1insert 1log 4read 4write;通过参数可以修改读写线程的数量innodb_%_io_threads
  • Purge Thread:回收已经使用并分配的undo页,事务提交后undo页可能不再需要;innodb1.2以后可以支持多个Purge Thread,进一步加快undo页的回收
  • Page Cleaner Thread:在innodb1.2.x版本引入,将master线程中的脏页刷新操作放到单独的线程中执行

2.3 内存

2.3.1缓冲池
  • innodb存储引擎是基于磁盘存储的,将记录按照页的方式进行管理
  • CPU和磁盘速度差别太大,因此需要使用缓冲池技术提高数据库效率
  • 读操作:在数据库中读取页的操作,首先将从磁盘读到的页放到缓冲池中“FIX”,下一次在读取相同的页时,先判断该页是否在缓冲池中,若在,则命中该页,然后读取
  • 写操作:首先修改在缓冲池中的页,然后以一定的频率(checkpoint机制)刷新回磁盘;5.配置innodb_buffer_pool_size来设置缓冲池大小
  • 缓冲池数据类型:索引页、数据页、undo页、插入缓冲、自适应哈希索引、innodb存储的锁信息、数据字典信息
  • 可以配置多个缓冲池实例,每个页根据哈希值平均分到不同的缓冲池实例中
  • 可以通过information_schema架构下的innodb_buffer_pool_stats查看缓冲池的情况。
2.3.2内存管理
  • 缓冲池是通过LRU(latest Recent Used)算法管理:最频繁使用的页放在LRU的前端,最小使用的页放在尾端,当缓冲池不能存放新读取的页时,首先释放LRU尾端的页。
  • LRU列表加入了midpoint位置,新读取的页并不是直接放入到LRU列表的首部,而是放到LRU列表的midpoint位置,该位置默认在LRU列表长度的5/8处,midpoint由innodb_old_blocks_pct控制。
  • midpoint原因:索引或者数据的扫描操作。需要访问表中的许多页,而这些页仅在这次查询操作中需要,不是热点数据。
    引入参数innodb_old_blocks_time管理LRU列表,标识页读到mid位置等待多久才会被加入到LRU列表的热端。
  • free列表:数据库刚启动时,LRU列表是空的,页都放在free列表中。缓冲池读取数据时,先找free中的空闲页,如果有,直接将页加在LRU列表上,然后写数据。否则根据LRU算法淘汰末尾的页,分配空间给新的页。
  • 脏页:LRU列表中的页被修改后称为脏页,缓冲池中的页和磁盘中的页上的数据产生了不一致。数据库会通过checkpoint机制将脏页刷新回磁盘。脏页也存在flush列表,lru列表用来管理缓冲池中页的可用性,Flush列表用来管理将页刷新会磁盘。
2.4 重做日志缓冲
  • 重做日志先放入到缓冲区,然后以一定的频率刷新到日志文件,缓冲区大小由innodb_log_buffer_size控制。
  • 重做日志缓冲刷新到重做日志文件的条件:Master Thread每一秒刷新一次;每个事务提交时会刷新;当重做日志缓冲剩余空间小于1/2时刷新。

3 innodb关键特性

3.1 插入缓冲

3.1.1 insert buffer
  • insert buffer和数据页一样,是物理页的一个部分。
  • 背景:非聚集索引的插入不是顺序,需要离散的访问非聚集索引页,导致插入性能下降。
  • 方案:先判断插入的非聚集索引页是否在缓冲池中,若在直接插入。否则先放入到一个Insert Buffer中,然后以一定的频率和情况进行Insert buffer和辅助索引页字节点merge。
  • 条件:索引是辅助索引,不是唯一索引(不做唯一性校验)。
  • 缺陷:写密集的情况下insert buffer会过多的占用缓冲池的空间,默认最大是1/2。
3.1.2 Insert buffer的内部实现
  • 数据结构是一棵B+树,全局只有一棵B+树,存放在共享表空间中,默认是ibdata1。
  • 试图通过独立表空间ibd文件恢复表中数据时,需要repair table重建辅助索引。
  • B+树非叶节点存放键值:space+marker+offset,space表示插入的表空间id,offset表示页所在的偏移量。
3.1.3 Merge Insert Buffer

合并时机:

  • 当辅助索引页读取到缓冲池中时(也就是通过辅助索引查询数据),需要检查辅助索引页是否有记录存在Insert Buffer B+树,如果有就发生merge操作。
  • 当插入辅助索引时,检查插入记录后可用空间会小于1/32,则会强制进行合并操作。
  • Master Thread每10秒执行一次Merge Insert Buffer操作。

3.2两次写double write

  • 概念:当写入失效发生时,先通过页的副本来还原该页,然后通过重做日志重做,这就是doublewrite。
  • 组成:一部分是内存中的double write buffer,另一部分是物理磁盘共享表空间中的连续的128个页,也就是两个区。
  • 方案:在对缓冲池的脏页进行刷新时,并不直接写磁盘。而是通过memcpy函数将脏页复制到内存的double write buffer中,然后分两次写入共享表的磁盘空间中,然后马上调用fsync函数,同步磁盘。

3.3 自适应哈希索引AHI

条件:

  • 访问模式一样,通过辅助索引的查询条件一样
  • 以该模式访问了100次
  • 页通过该模式访问了N次,N=页中记录/16

3.4 异步IO

  • 当前的数据库系统都是采用异步IO的方式来处理磁盘操作
  • 可以进行IO Merge操作,将多个IO合并为一个IO
  • innodb提供了内核级别的AIO的支持,通过参数innodb_use_native_aio控制

3.5 刷新邻接页

  • 当刷新一个脏页时,会检测该页所在区的所有页,如果是脏页,一起进行刷新。
  • 通过参数innodb_flush_neighbors控制。

4 checkpoint技术

  • 背景:事务提交时,需要先写重做日志,再修改页。宕机发生数据丢失时,通过重做日志来完成数据的恢复。这也是ACID中D(持久性)的要求。
  • 目的:1.缩短数据库的恢复时间;2.缓冲池不够用时,将脏页刷新到磁盘;3.重做日志不可用时,刷新脏页。
  • 技术:1.当缓冲池不够用,根据LRU溢出页时,检查页如果是脏页,强制执行checkpoint刷新回磁盘;2.当数据库发生宕机时,将缓冲池中的页刷新到当前重做日志的位置。
  • 分类:Sharp Checkpoint,在数据库关闭时,刷新所有的脏页回磁盘;Fuzzy Checkpoint,每次刷新一部分脏页,各线程对checkpoint处理
#MySQL##笔记##读书笔记#
全部评论
马一下
点赞 回复 分享
发布于 2018-07-24 10:54

相关推荐

09-27 14:42
已编辑
浙江大学 Java
未来未临:把浙大放大加粗就行
点赞 评论 收藏
分享
不愿透露姓名的神秘牛友
09-30 19:49
起名星人:蛮离谱的,直接要求转投销售
投递汇川技术等公司10个岗位
点赞 评论 收藏
分享
点赞 16 评论
分享
牛客网
牛客企业服务