快速预热Innodb Buffer Pool的方法
当innodb_buffer_pool_size大到几十GB或是百GB的时候,因为某些日常升级更新或是意外宕机,而必须要重新启动mysqld服务的之后,就面临一个问题,如何将之前频繁访问的数据重新加载回buffer中,也就是说,如何对innodb buffer pool进行预热,以便于快速恢复到之前的性能状态。如果是光靠Innodb本身去预热buffer,将会是一个不短的时间周期,业务高峰时,数据库将面临相当大的考验,I/O的瓶颈会带来糟糕的性能。那么,该怎么办呢?于是大家便想出一些办法,最后Percona把这个需求,在XtraDB中最为一个新特性实现这个功能。
早期,Peter在实际的工作中总结了一些预热buffer pool的SQL语句,也就是通过人为模拟一些请求,尽可能地将我们所需的数据块和索引加载到内存中。
1. 加载主键索引
select count(*) from tbl where no_index_col=0;
2. 加载非主键索引
select count(*) from tbl where index_col like “%0%”;
3. 加载BLOB/TEXT列
select count(*) from tbl where blob_col like “%0%”;
4. 分段加载大表数据
select count(*) from tbl where id between 1 and 10000000 and no_index_col=0;
还有人使用blackhole引擎来进行预热操作,通过替换不同的索引字段进行排序查询,将所需数据加载。
create table temp_blackhole like tbl;
alter table temp_blackhole engine=blackhole;
select * from tbl order by id into temp_blackhole;
现在,Percona已经完全在XtraDB中实现这个功能,最初采用Share Memory Buffer Pool,目前采用Dump/Restore of the Buffer Pool。
1. Share Memory Buffer Pool
该方法在内存个划出一个共享段用于存储buffer pool,使得这块空间在mysqld启动关闭前后都能备份访问,不会因为mysqld关闭而将buffer pool的内容清除。但是,共享内存的使用必须遵守严格的要求:innodb引擎前后保持一致;innodb的page页大小前后保持一致;innodb_buffer_pool_size的大小前后保持一致。否则,会遇到问题,这时就不能在使用共享空间,需要手动将其删除。
innodb_buffer_pool_shm_key ― 用于是否开启共享内存的使用,0开启,1不开启。
innodb_buffer_pool_shm_checksum ― 检查共享空间中存储的buffer pool是否有损坏。
/proc/sys/kernel/shmmax ― 内存共享空间的大小可以通过系统下的该文件去调整。
2. Dump/Restore of the Buffer Pool
从名字就可以知道这个预热方法,先将buffer pool的内容dump出来,在数据目录下会生成一个ib_lru_dump的文件,然后需要是再通过这个dump文件将其恢复回去,这也正是我们最初的一个想法。下面简单说下它的实现过程,先需要了解下Innodb buffer pool。
Innodb Buffer Pool是内存中的一段存储空间,由大小为16KB的page页组成,是一个列表页,该列表按照LRU的顺序进行排列,所以也被叫作LRU列表。buffer pool被分成两个子列,前半段被称为’young’,也就是经常被访问到的块,而后半段成为’old’,访问次数较少的块。当有新的块被加载进来的时候,会被插入到两端之间的位置,之后会随着被访问的频繁程度,是保持迁移还是不断后退,最后被替换出去。
在了解了Innodb Buffer Pool之后,让我么来看看dump操作。我们知道磁盘的查找更多是无序的随机的操作,而加载到内存中的page会被重新组织成有序的排列。XTRA_LRU_DUMP的操作并不是简单的将innodb_buffer_pool中的所有内容备份到ib_lru_dump文件中,这样会随着innodb_buffer _pool_size的大小而变得很大,进而备份恢复时间也会变得不很乐观,那么怎么做呢?事实上,只需备份page在buffer pool中的标志信息即可,即(space_id,page_no)这样一个列表,space_id表示page在buffer pool中LRU的排列顺序,page_no表示page在磁盘上的存储位置。恢复时,按照page_no去磁盘中找到对应的page,而这个可以按照page_no的顺序去查找,可以近似看作是顺序i/o,尽量避免随机i/o的消耗,然后将查找到的page按照space_id存到最初在LRU列表中的位置,最后实现恢复到关闭服务之前的状态。这个方法提供了自动和手动两种实现操作。
自动参数设置:
innodb_buffer_pool_restore_at_startup/innodb_auto_lru_dump ― 该参数可以控制是否开启自动dump/restore的操作,只能通过手动完成;当为0时,表示不开启自动操作,当为非0时,表示按照指定的时间周期dump操作,重启后自动完成restore的操作。
P.S.: 该特性的选项innodb_auto_lru_dump是在XtraDB的5.5.10-12.1版本中被引入,到5.5.10-20.1起将其重名为innodb_buffer_pool_restore_at_startup。
手动操作如下:
mysql> show status like ‘innodb_buffer_pool_pages_data’; ― 查看重启前后当前page页的个数
mysql> select * from information_schema.XTARDB_ADMIN_COMMAND /*!XTRA_LRU_DUMP*/; ― 备份innodb_buffer_pool
mysql> select * from information_schema.XTARDB_ADMIN_COMMAND /*!XTRA_LRU_RESTORE*/; ― 恢复innodb_buffer_pool
P.S.: 以上手动备份恢复的操作语句还没有加入到XtraDB的任何版本中,只是在Percona的test环境中实现了。
- TAKEAWAYS -
Innodb Buffer Pool是InnoDB性能提升的核心,它既可以缓存数据还可以缓存索引。缓存的数据部分是数据块构成的page页,而不像Query Cache仅存的SQL对应的结果集。Buffer Pool上可以完成数据的更新变化,减少随机i/o的操作,提高写入性能,而Query Cache最忌讳表的数据更新,会导致相应的cache失效,带来额外系统消耗。之前听过这么一句很精辟的对于buffer与cache的总结:buffer是用来加速写,cache是用来缓冲读。在实际中,尽可能的增大innodb_buffer_pool_size的大小,把频繁访问的数据都放到内存中来,尽可能减少Innodb对于磁盘i/o的访问,把InnoDB最大话成为一个内存型引擎。
innodb_buffer_pool_size的大小,当系统启动后,会比之前指定的要多出大小的10%,避免过大导致OS发生swap动作,留出足够的给OS使用;show engine innodb status\G命令输出中BUFFER POOL AND MEMORY部分有关于buffer pool使用情况的提示,可以关注这么三项:Free buffers表示未被使用的,经过一段时间后,仍然保持不少的空闲buffer,说明该参数设置过大,如果为0,说明该参数设置的大小不能满足需求;Database pages表示目前有多少数据页已经被缓存到buffer pool中;flush list表示dirty pages的数量,有多少跟新的页没有被刷回磁盘,当缓存的列表太大时,会使正常关闭mysqld变得很慢,也会使意外发生后Crash Recovery的动作只持续相当长时间(会是你无法忍受的);Buffer pool hit rate表示buffer pool的使用效率。
建议继续学习:
- Buffer和cache的区别是什么? (阅读:6823)
- Innodb IO优化-配置优化 (阅读:6626)
- Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (阅读:6131)
- Linux操作系统中内存buffer和cache的区别 (阅读:5305)
- Innodb 表和索引结构 (阅读:4774)
- Innodb如何使用内存 (阅读:4002)
- InnoDB线程并发检查机制 (阅读:4084)
- MySQL数据库InnoDB存储引擎 Buffer pool LRU List Flush策略详解 (阅读:3773)
- InnoDB的缓存替换策略及其效果 (阅读:3638)
- 多版本并发控制:PostgreSQL vs InnoDB (阅读:3631)
扫一扫订阅我的微信号:IT技术博客大学习
- 作者:zhang 来源: SQL部落
- 标签: Buffer Innodb 预热
- 发布时间:2011-07-24 15:13:32
- [67] Go Reflect 性能
- [67] Oracle MTS模式下 进程地址与会话信
- [67] 如何拿下简短的域名
- [61] IOS安全–浅谈关于IOS加固的几种方法
- [60] 图书馆的世界纪录
- [59] 【社会化设计】自我(self)部分――欢迎区
- [58] android 开发入门
- [56] 视觉调整-设计师 vs. 逻辑
- [49] 给自己的字体课(一)——英文字体基础
- [47] 界面设计速成