IT技术博客大学习 共学习 共进步

快速预热Innodb Buffer Pool的方法

SQL部落 2011-07-24 15:13:32 浏览 4,982 次

当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的使用效率。

建议继续学习

  1. Buffer和cache的区别是什么? (阅读 7,841)
  2. Innodb IO优化-配置优化 (阅读 7,603)
  3. Innodb分表太多或者表分区太多,会导致内存耗尽而宕机 (阅读 7,565)
  4. Linux操作系统中内存buffer和cache的区别 (阅读 6,341)
  5. Innodb 表和索引结构 (阅读 6,041)
  6. InnoDB线程并发检查机制 (阅读 5,601)
  7. Innodb如何使用内存 (阅读 5,101)
  8. Innodb文件表空间结构 (阅读 5,062)
  9. MySQL数据库InnoDB存储引擎 Buffer pool LRU List Flush策略详解 (阅读 4,922)
  10. InnoDB的缓存替换策略及其效果 (阅读 4,781)