innodb buffer pool相关特性

背景

innodb buffer pool作为innodb最重要的缓存,其缓存命中率的高低会直接影响数据库的性能。因此在数据库发生变更,比如重启、主备切换实例迁移等等,innodb buffer poll 需要一段时间预热,期间数据库的性能会受到明显影响。
另外mysql 5.7以前innodb buffer pool缓存大小修改不是动态的,重启才能生效。因此innodb buffer pool的预热和innodb buffer pool大小的动态修改,对性能要求较高的应用来说是不错的特性,下面我来看看这两个特性的具体实现。

buffer pool 预热

mysql 5.6以后支持buffer pool预热功能。引入了以下参数, 参数具体含义参见官方文档

innodb_buffer_pool_load_now
innodb_buffer_pool_dump_now
innodb_buffer_pool_load_at_startup
innodb_buffer_pool_dump_at_startup
innodb_buffer_pool_filename

buffer pool预热分为dump过程和load过程,均由后台线程buf_dump_thread完成。
比如用户发起set命令

set global innodb_buffer_pool_dump_now=on;
set global innodb_buffer_pool_load_now=on;

set 命令会立刻返回,具体操作由buf_dump_thread来实现。

  • dump 过程

    锁buf_pool
    遍历LRU链表,将(space, pageno) 先收集到数组
    释放锁
    再将数据写入innodb_buffer_pool_filename定有的文件中

  • load过程

    从文件读入数组
    按(space,pageno)排序数据
    依次同步读取页到buffer pool中

dump过程一般比较快,而load过程相对要慢些。

通过Innodb_buffer_pool_dump_statusInnodb_buffer_pool_load_status可查看dump/load的状态

另外5.7引入了performance_schema.events_stages_current来显示load进度,每load 32M会更新一条进度信息

select * from performance_schema.events_stages_current;
THREAD_ID       19
EVENT_ID        1367
END_EVENT_ID    NULL
EVENT_NAME      stage/innodb/buffer pool load
SOURCE  buf0dump.cc:619
TIMER_START     33393877311000
TIMER_END       33398961258000
TIMER_WAIT      5083947000
WORK_COMPLETED  0
WORK_ESTIMATED  1440
NESTING_EVENT_ID        NULL
NESTING_EVENT_TYPE      NULL

WORK_ESTIMATED表示总page数
WORK_COMPLETED表示当前已load page数

dump文件的数据格式如下

#cat ib_buffer_pool |more
0,7
0,1
0,3
0,2
0,4
0,11
0,5
0,6

dump文件比较简单,我们可以编辑此文件来预加载指定page,比较灵活。

buffer pool 动态调整大小

5.7 开始支持buffer pool 动态调整大小,每个buffer_pool_instance都由同样个数的chunk组成(chunks数组), 每个chunk内存大小为innodb_buffer_pool_chunk_size(实际会偏大5%,用于存放chuck中的block信息)。buffer pool以innodb_buffer_pool_chunk_size为单位进行动态增大和缩小。调整前后innodb_buffer_pool_size应一直保持是innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的倍数。

同样的buffer pool动态调整大小由后台线程buf_resize_thread,set命令会立即返回。通过InnoDB_buffer_pool_resize_status可以查看调整的运行状态。

  • resize流程

    • 如果开启了AHI,需禁用AHI
    • 如果是收缩内存
      1. 计算需收缩的chunk数, 从chunks开始尾部删除指定个数的chunk.
      2. 锁buf_pool
      3. 从free_list中摘除待删chunk的page放入待删链表buf_pool->withdraw
      4. 如果待删chunk的page为脏页,则刷脏
      5. 重新加载LRU中要删除的页,从LRU中摘除,重新从free列表获取page老的page放入待删链表buf_pool->withdraw
      6. 释放buffer pool锁
      7. 如果需收缩的chunk pages没有收集全,重复2-6
    • 开始resize
      1. 锁住所有instance的buffer_pool,page_hash
      2. 收缩pool:以chunk为单位释放要收缩的内存
      3. 清空withdraw列表buf_pool->withdraw
      4. 增大pool:分配新的chunk
      5. 重新分配buf_pool->chunks
      6. 如果改变/缩小超过2倍,会重置page hash,改变桶大小
      7. 释放buffer_pool,page_hash锁
      8. 如果改变/缩小超过2倍,会重启和buffer pool大小相关的内存结构,如锁系统(lock_sys_resize),AHI(btr_search_sys_resize), 数据字段(dict_resize)等
    • 如果禁用了AHI,此时开启

由上可以看出,扩大内存比缩小内存相对容易些。缩小内存时,如果遇到有事务一直未提交且占用了待收缩的page时,导致收缩一直重试,error log会打印这种重试信息,
包含可能引用此问题的事务信息。为了避免频繁重试,每次重试的时间间隔会指数增长。

以上步骤中resize阶段buffer pool会不可用,此阶段会锁所有buffer pool, 但此阶段都是内存操作,时间比较短。收缩内存阶段耗时可能会很长,也有一定影响,但是每次都是以instance为单位进行锁定的。
总的来说,buffer pool 动态调整大小对应用的影响并不大。

  • 重新加载LRU中要删除的页的影响

    search 过程中btr游标保存的page可能重新加载过,自适应哈希保存的root page也可能重新加载过, 都需要重新读取。

总结

buffer pool 预热 和buffer pool 动态调整大小,这两功能相辅相承的。buffer pool 动态调整大小只适用于实例在主机本地升级的情况,如果用户修改buffer pool大小,同时涉及跨机迁移,那么buffer pool 预热功能就排上用场了。
另外buffer pool 动态调整尽量在业务低锋时进行。

时间: 2024-08-03 23:11:33

innodb buffer pool相关特性的相关文章

MySQL · 特性分析 · innodb buffer pool相关特性

背景 innodb buffer pool做为innodb最重要的缓存,其缓存命中率的高低会直接影响数据库的性能.因此在数据库发生变更,比如重启.主备切换实例迁移等等,innodb buffer poll 需要一段时间预热,期间数据库的性能会受到明显影响. 另外mysql 5.7以前innodb buffer pool缓存大小修改不是动态的,重启才能生效.因此innodb buffer pool的预热和innodb buffer pool大小的动态修改,对性能要求较高的应用来说是不错的特性,下面

MySQL · 引擎特性 · InnoDB Buffer Pool

前言 用户对数据库的最基本要求就是能高效的读取和存储数据,但是读写数据都涉及到与低速的设备交互,为了弥补两者之间的速度差异,所有数据库都有缓存池,用来管理相应的数据页,提高数据库的效率,当然也因为引入了这一中间层,数据库对内存的管理变得相对比较复杂.本文主要分析MySQL Buffer Pool的相关技术以及实现原理,源码基于阿里云RDS MySQL 5.6分支,其中部分特性已经开源到AliSQL.Buffer Pool相关的源代码在buf目录下,主要包括LRU List,Flu List,Do

MySQL内核月报 2015.02-MySQL · 性能优化· InnoDB buffer pool flush策略漫谈

背景 我们知道InnoDB使用buffer pool来缓存从磁盘读取到内存的数据页.buffer pool通常由数个内存块加上一组控制结构体对象组成.内存块的个数取决于buffer pool instance的个数,不过在5.7版本中开始默认以128M(可配置)的chunk单位分配内存块,这样做的目的是为了支持buffer pool的在线动态调整大小. Buffer pool的每个内存块通过mmap的方式分配内存,因此你会发现,在实例启动时虚存很高,而物理内存很低.这些大片的内存块又按照16KB

MySQL5.7: 动态调整buffer pool size

在5.7.5中提供了一个新功能,能够动态的对buffer pool size进行调整. 对应的changelog entry: InnoDB: The innodb_buffer_pool_size parameter is now dynamic, allowing you to resize the buffer pool without restarting the server. The resizing operation, which involves moving pages to

从MySQL的源码剖析Innodb buffer的命中率计算_Mysql

按官方手册推荐Innodb buffer Hit Ratios的计算是:   100-((iReads / iReadRequests)*100) iReads : mysql->status->Innodb_buffer_pool_reads iReadRequests: mysql->status->Innodb_buffer_pool_read_requests 出处: http://dev.mysql.com/doc/mysql-monitor/2.0/en/mem_gra

揭秘SQL Server 2014有哪些新特性(2)-固态硬盘 Buffer Pool(缓冲池) 扩展_MsSql

简介     SQL Server 2014中另一个非常好的功能是,可以将SSD虚拟成内存的一部分,来供SQL Server数据页缓冲区使用.通过使用SSD来扩展Buffer-Pool,可以使得大量随机的IOPS由SSD来承载,从而大量减少对于数据页的随机IOPS和PAGE-OUT. SSD AS Buffer Pool     SSD是固态硬盘,不像传统的磁盘有磁头移动的部分,因此随机读写的IOPS远远大于传统的磁盘.将SSD作为Buffer Pool的延伸,就可以以非常低的成本巨量的扩充内存

简要记录一下压缩表在buffer pool中的相关结构体:

//////////////////////////////////////////////////////////// struct buf_pool_struct{ mutex_t     zip_mutex;   //用于保护压缩page(buf_page_t) mutex_t     zip_free_mutex; mutex_t     zip_hash_mutex;   //保护zip_hash hash_table_t*   zip_hash;  //hash table of b

MySQL 5.7.5: Buffer Pool 转储、恢复 以及存在的问题

MySQL提供了一个比较有用的功能,能够把buffer pool LRU上的block对应的page id 和space id 存储到文件中.在重启时,会自动读取这个转储文件,然后把对应的<space id, page id>读入到buffer pool中,快速预热内存,以尽快提供服务. 参数 使用该特性比较简单,通过多个参数控制. 简单说下几个参数 转储到文件: innodb_buffer_pool_dump_now  : 立刻做一次buffer pool  LRU dump innodb_

千丝万缕的FGC与Buffer pool

1 背景 运维通知,线上系统一直在FGC,通过zabbix查看GC 的次数 再查看YGC和FGC空间占用情况 这里有几个疑问: 1:old space 空间一直很低,为什么会有频繁的FGC? 2:Eden space 回收的阈值为什么越来越低,越来越频繁? 3:从Eden space空间看一直在YGC,但是从YGC的次数看并没有过YGC? 4:FGC的越来越频繁,到最后为什么一直在FGC? 第一个问题 通过查看打印出来的ERROR日志,确定是Direct buffer 不够.在申请DirectB