ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

buffer pool 的内部原理和结构

2022-06-16 18:35:02  阅读:151  来源: 互联网

标签:存储 buffer 链表 LRU 原理 pool 页面


InnoDB architecture diagram showing in-memory and on-disk structures.

行记录     

  


变长字段长度列表:存储变长字段的长度,如varchar、text、blob

null值列表:记录各列是否为null  1:null  0:非null

隐藏列 ROW_ID: 没有创建主键 并且没有唯一索引的时候会默认创建 rowId,,否则不创建

    trx_id:事务的id

    roll_ptr:回滚的id

记录头信息:5个字节

    delete_mark :删除标志

    min_rec_mark: B+树每层非叶子节点中最小的记录会记录本值

    n owned:一个槽中索引最大的行会存储此值,记录这个槽中有多少条记录

    heap_no:记录在页的位置

    record_type: 0:普通记录、1:非叶子节点、2:最小记录、3:最大的记录

    next_record:下一条记录的地址,在一个数据页中记录的是单向列表,下一条记录 不是按照插入顺序记录的 是按照键值的大小排序的。

行记录的格式分为:compect 、dynamic、compress、redundant

各个格式之间的区别

redundant:5.0以前的版本

compect:对于数据溢出,一页存不下的行,可存储前768的数据,后面用20个字节指向溢出页的地址

dynamic:会把所有的字段都存储到溢出页,只记录溢出页的地址

compress;采用压缩算法对页面数据进行压缩,对于溢出数据同dynamic的处理方式

 

 

 File header: 38个字节,存储的是页面的编号、上一页 下一页、存储验证码,各种类型的页面通用的。

 File trailer: 8个字节    前四个字节存储和fileheader 一致的验证码,后四个字节存储修改时对应的日志位置。

page head: 56个字节 ,存储该页面又多少行记录、多少槽、第一条记录的地址是多少

user records:存储的是用户数据,存储的是一个链表,当一行记录被删除了,delete_mark被标记成1,从该链表中删除,增加到可复用的链表中,而不是回收这块空间,因为回收空间会引起页面的分裂重新排序浪费性能

infimum:+ supremum:26个字节  内容是0  本页数据中的最小值

supremum:本页数据中的最大值 内容是1

page directory:记录每个槽中最大记录的偏移地址,为了解决一个页面通过链表查询数据慢的情况,引入了槽的概念,使用槽先进性二分查找,找到具体的槽之后 进行链表遍历,变得链表最大长度为8,类似于hashmap,

 

 

 

free space:未被占用的空间

一个页用16k的大小

 

 

 

在屋里内存上是一块连续的空间,写入的时候是顺序io,包含64个页,也就是一个区有1个M的空间

每256个区被划分成一组,表空间的第一个组用于存储一些整体属性,每组开始的两个页面用于存储256个区的一些属性

可分为叶节点段,非叶子节点段,回滚段,用于全表扫描可剩更少的内存

innobd的磁盘空间分布

独立表空间

用于存储.idb文件,如果innodb_file_per_table 为ON则存储在表空间  否则 存储在通用表空间

系统表空间

存储了双写缓冲区、数据字典的系统表等

共享表空间

临时表空间

双写缓冲区(doublewrite buffer)

buffer pool中也有一份,2个区,也就是2M。innnodb是按照页尾单位写入磁盘的,每个页16kb,但是磁盘写入的单位 每个扇区一般是4k,所以写入一页要分4次写入,如果在写入磁盘的过程中发生了宕机情况就会造成数据页损坏;

等到下次重启的时候,因为redolog是存储的更改逻辑,需要结合原数据进行数据合并后得到正确的结果,单数数据页损毁原数据不在,所以这种情况不能通过redolog进行修复。

即引入了双写缓存区, 先写在磁盘的双写缓冲区里,在写入独立表空间。如果表空间的的数据页损毁 可通过双写缓冲区进行恢复;

如果双写缓冲区也损毁 则通过redolog 进行恢复,因为此时表空间的原始数据没有损毁;

因为需要两次io 所以开启了双写缓冲区 会增加性能的消耗 一般在5%~10%之间。

开启双写缓冲区参数:innodb_doublewrite

数据字典

SYS_TABLES  整个InnoDB存储引擎中所有的表的信息

SYS_COLUMNS  整个InnoDB存储引擎中所有的列的信息

SYS_INDEXES  整个InnoDB存储引擎中所有的索引的信息

SYS_FIELDS  整个InnoDB存储引擎中所有的索引对应的列的信息

SYS_FOREIGN  整个InnoDB存储引擎中所有的外键的信息

SYS_FOREIGN_COLS  整个InnoDB存储引擎中所有的外键对应列的信息

SYS_TABLESPACES 整个InnoDB存储引擎中所有的表空间信息

SYS_DATAFILES  整个InnoDB存储引擎中所有的表空间对应文件系统的文件

change buffer/insert buffer

是bufferpool中的一块空间,默认占25%,磁盘中持久化放在系统表空间里

 

 

 是针对二级索引更改的优化,是更改逻辑的缓存。不着急进行io写入,等数据进行访问、空闲时刻、正常关机的情况下 进行merge,

 

redolog

undolog

buffer pool 的结构

是mysql 启动时像os申请的一块空间

存储数据、change buffer、redolog

 

show  status   like "%Innodb_buffer_pool_pages%";

 

 

 Innodb_buffer_pool_pages_data:占用的数据页

Innodb_buffer_pool_pages_dirty:脏页

Innodb_buffer_pool_pages_flushed:被刷的脏页

Innodb_buffer_pool_pages_free:空闲页

Innodb_buffer_pool_pages_misc:其他系统数据占用的页

Innodb_buffer_pool_pages_total:buffer pool的总页数

buffer pool的内存大小

show variables like "%innodb_buffer_pool_size%";

展示的为字节数,是128M,在使用单独的服务器时,官方建议设置成内存的80%,但是还有一些额外的内存可能会占用到90%,所以一般是60%~75%左右,这个值由DBA根据系统业务高峰期 内存占用率具体设置

buffer pool的free list

 

 

 

内存会分成一个个的页大小的空间,并增加对应的控制块(这个控制块并不占用buffer pool的申请的内存)

控制块中包括该页所属的表空间编号、页号、缓存页在Buffer Pool中的地址、链表节点信息、一些锁信息以及LSN信息,当然还有一些别的控制信息。

没有被使用的页的控制块组成的双向列表称为 free list;

当需要寻找寻找一页数据页看是否在缓存中时  适应表空间号+页号当做key 在hash列表中可以找到对应的页,如果没有需要去磁盘中加载

buffer pool的flush list

脏页对应控制块组成的双向列表称为 flush list

简单的LRU list的算法规则

用内存就需要用到内存淘汰的机制,

 LRU :least recently used   每次访问被访问的数据就添加到列表的头部。慢慢的不经常的访问的数据就会被过滤到尾部,淘汰时先从尾部淘汰

预读

INNODB 根据计算机的局部性原理 会预读数据

线性预读:当访问的页超过 56(innodb_read_ahead_threshold)就会把整个区读入缓存

局部预读:当一个区中访问的页超过13个 无论些是不是连续的 就会把整个区读入缓存 默认该功能是关闭的 innodb_random_read_ahead

预读和全表扫描的情况下简单的LRU list的产生的后果

全表扫描数据量大 势必会淘汰一部分之前的内存,其中会包含热数据

预读的数据会放在优先访问的位置,使原来的热数据后移如果预读的数据不会被使用 则大大降低了缓存的命中

buffer pool的LRU改进点

将LRU list 分为两部分 前部分为热数据 成为 yong区,后面为冷数据 成为old区;
innodb_old_blocks_pct  默认是37 也就是old区占比3/8 

新缓存进来的页放入old区

设置old区页面访问的间隔,SHOW VARIABLES LIKE 'innodb_old_blocks_time';  默认是1s 也就是说old区的页面第一次访问和最后一次访问的时间间隔不到一秒 会默认是全表扫描的页面 不加入yang区;

对于yong区的数据 后面四分之一的数据被击中才需要移到前面

刷脏页

多个buffer pool

show variables like "%innodb_buffer_pool_instances%"; 默认是1,设置多个buffer pool的实例可以增加并发的性能,最小是1  最大的64,如果每个实例内存分配不到1个G则强制为1;

内存分配innodb_buffer_pool_size/innodb_buffer_pool_instances

chunk

5.7.5之后的版本可以在系统运行时设置buffer pool的大小;

为了不要把原内存的数据重新复制到新的空间 引入了chunk的概念,默认是128M innodb_buffer_pool_chunk_size;

以chunk为单位向系统申请空间

 

 

SHOW ENGINE INNODB STATUS\G buffer pool的系统状态

 

 Total memory allocated:代表Buffer Pool向操作系统申请的连续内存空间大小,包括全部控制块、缓存页、以及碎片的大小。

Dictionary memory allocated:为数据字典信息分配的内存空间大小,注意这个内存空间和Buffer Pool没啥关系,不包括在Total memory allocated中。

Buffer pool size:代表该Buffer Pool可以容纳多少缓存页,注意,单位是页!

Free buffers:代表当前Buffer Pool还有多少空闲缓存页,也就是free链表中还有多少个节点。

Database pages:代表LRU链表中的页的数量,包含young和old两个区域的节点数量。

Old database pages:代表LRU链表old区域的节点数量。

Modified db pages:代表脏页数量,也就是flush链表中节点的数量。

Pending reads:正在等待从磁盘上加载到Buffer Pool中的页面数量。当准备从磁盘中加载某个页面时,会先为这个页面在Buffer Pool中分配一个缓存页以及它对应的控制块,然后把这个控制块添加到LRU的old区域的头部,但是这个时候真正的磁盘页并没有被加载进来,Pending reads的值会跟着加1。

Pending writes LRU:即将从LRU链表中刷新到磁盘中的页面数量。

Pending writes flush list:即将从flush链表中刷新到磁盘中的页面数量。

Pending writes single page:即将以单个页面的形式刷新到磁盘中的页面数量。

Pages made young:代表LRU链表中曾经从old区域移动到young区域头部的节点数量。

Page made not young:在将innodb_old_blocks_time设置的值大于0时,首次访问或者后续访问某个处在old区域的节点时由于不符合时间间隔的限制而不能将其移动到young区域头部时,Page made not young的值会加1。

youngs/s:代表每秒从old区域被移动到young区域头部的节点数量。

non-youngs/s:代表每秒由于不满足时间限制而不能从old区域移动到young区域头部的节点数量。

Pages read、created、written:代表读取,创建,写入了多少页。后边跟着读取、创建、写入的速率。Buffer pool hit rate:表示在过去某段时间,平均访问1000次页面,有多少次该页面已经被缓存到Buffer Pool了。

young-making rate:表示在过去某段时间,平均访问1000次页面,有多少次访问使页面移动到young区域的头部了。

not (young-making rate):表示在过去某段时间,平均访问1000次页面,有多少次访问没有使页面移动到young区域的头部。

LRU len:代表LRU链表中节点的数量。

unzip_LRU:代表unzip_LRU链表中节点的数量。

I/O sum:最近50s读取磁盘页的总数。

I/O cur:现在正在读取的磁盘页数量。

I/O unzip sum:最近50s解压的页面数量。

I/O unzip cur:正在解压的页面数量。

自适应hash

 

 

 

标签:存储,buffer,链表,LRU,原理,pool,页面
来源: https://www.cnblogs.com/xiatc/p/16382983.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有