MYSQL如何减少磁盘 IO ?——BufferPool

270 阅读2分钟

如何减少磁盘 IO ?

MYSQL Innodb底层采用了B+树数据结构。
而B+树有一个优点,可以减少树的层高,从而减少磁盘IO
除此之外,MYSQL还采用了BufferPool去减少磁盘IO。


BufferPool ( 缓冲池 )

1、作用

用来缓存表数据索引数据,减少磁盘 IO ,提升效率。

graph RL 
    subgraph Mysql Innodb  
        page[缓存数据页-16kb<br>一行数据<br>一行数据<br>...]
        db[(磁盘文件)]
        db -->|读取| page
        page -->|加载到BufferPool| page03
        subgraph BufferPool:默认128M
            block01(控制块-约800b)
            block02(控制块)
            block03(控制块...)
            page01(缓存数据页-16kb)
            page02(缓存数据页)
            page03(缓存数据页...)
        end
        block01 -.- page01
        block02 -.- page02
        block03 -.- page03
    end
    

2、Buffer Pool 组成 :

  • Buffer Pool: 默认大小128M (物理内存)
    • 控制块 : 大小约为数据页的 5%,大概是 800 字节
      • 对应缓存页所属的表空间、数据页的编号
      • 对应缓存页在 BufferPool 中的地址
      • 等等
    • 缓存数据页(Page): 默认大小16kb

每一个控制块对应一个缓存数据页。
内存分配推荐70~80%物理内存。

3、Page状态:

  • free page : 空闲 page,未被使用。
  • clean page: 被使用的page,数据没有被修改过。
  • dirty page: 被使用的page, 数据被修改过;脏页,Page数据和磁盘数据不一致。

4、Buffer Pool 数据页管理 :

Buffer Pool是通过是三个链表的使用来维护数据页的更新与淘汰

  • Free链表: 记录Buffer Pool空闲数据页。
  • Flush链表: 记录Buffer Pool脏页数据 脏页:更新BufferPool数据页,但还未到持久化磁盘
  • LRU链表: 记录Buffer Pool已保存数据页,并利用该链表实现淘汰机制

注:
Free链和Flush链表首个节点为基节点,存放链表的头节点、尾节点地址,以及当前链表存在多少节点。
其余都是保存控制块,再通过控制块访问缓存数据页。

5、LRU链表

Least Recently Used :最近最少使用。Mysql对LRU算法进行了优化,尽量减少全表扫描和预读的影响。
LRU链表前 58\dfrac{5}{8} 的区域称为热数据区域\color{red}{热数据区域}。 LRU链表后 38\dfrac{3}{8} 的区域称为冷数据区域\color{blue}{冷数据区域}
热数据区\color{red}{热数据区}冷数据区\color{blue}{冷数据区}中间节点叫midpoint
新增节点从midpoint插入
新增节点第二次访问时将节点移动到热数据区\color{red}{热数据区}头部 距第一次访问超过innodb_old_blocks_time生效,默认一秒
被挤出冷数据区\color{blue}{冷数据区}的节点则会被淘汰

6、如何判断一个页是否在 BufferPool 中缓存 ?

MySQl 中有一个哈希表数据结构,它使用表空间号+数据页号,作为一个 key,然后缓冲页对应的控制块作为 value。