[InnoDB系列] - InnoDB Buffer Pool保存和还原补丁

参考文章:Making MySQL more usable: InnoDB save/restore buffer pool patch
Jeremy Cole同学写了个补丁,用于将InnoDB 缓冲池(buffer pool)里的列表在关闭mysqld时保存到本地文件中,重启启动时再加载到内存中去。该补丁目前只适用于MySQL 5.1版本。作者计划该补丁至少应具备以下几点要求:

  • 可以自定义本地文件名
  • 可以在启动时自主选择是否需要加载到内存中
  • 支持在接受用户请求前先加载一部分,剩下的可以放到后台进程中继续加载

不过,作者目前只是想到了以下几点特性,虽然有的还没有实现:

  • 采用多线程来加载,这对于使用RAID阵列更有优势
  • 支持在线保存/还原缓冲池,而无需重启mysqld
  • 增加缓冲池的统计信息,便于在加载时能选择哪些优先级别比较高,避免所有的页都以同一优先级加载

下面我们来尝试用以下这个补丁,看看效果如何。

1、准备

下载innodb plugin 1.0.1,下载补丁buffer_pool_save_restore.patchmove_buf_chunk_struct.patch。下载MySQL 5.1.26源码。
然后是解压缩,打补丁,编译。

[yejr@localhost yejr]# cd innodb_plugin-1.0.1
[yejr@localhost yejr]# patch -p1 < ../buffer_pool_save_restore.patch
patching file handler/ha_innodb.cc
Hunk #1 succeeded at 1986 with fuzz 2 (offset 67 lines).
patching file include/srv0start.h
patching file srv/srv0start.c
Hunk #1 succeeded at 1950 (offset 18 lines).
[yejr@localhost yejr]# cd ..; alias cp=cp; cp -rf innodb_plugin-1.0.1/* mysql-5.1.26-rc/storage/innobase/
[yejr@localhost yejr]# cd mysql-5.1.26-rc
[yejr@localhost yejr]# ./configure '-without-embedded-server' '-with-innodb' '-with-zlib-dir=bundled' '-with-big-tables' '-enable-assembler' '-enable-local-infile' '-with-pic' '-prefix=/usr/local/mysql' '-with-extra-charsets=complex' '-enable-thread-safe-client' && make && make install-strip
[yejr@localhost yejr]# strings /usr/local/mysql/libexec/mysqld | grep ib_buf_pool_state

可以看到,已经将该补丁编译进去了。在这里,也可以下载 percona 提供的源码,里面已经集成了其他的几个补丁。

2、测试

首先,模拟各种方法,将innodb buffer pool尽量填满,最快的办法就是导出全部数据。设置 innodb_buffer_pool_size 大小为 14G,然后导出全部数据,可以看到全部被填满了:

...
Buffer pool size   917503
Free buffers       0
Database pages     917503
Modified db pages  0
...

关闭mysqld,查看一下是不是产生了本地文件。

[yejr@localhost yejr]# mysqladmin shut
[yejr@localhost yejr]# ls -lh ib_buf_pool_state
-rw-rw----  1 mysql mysql 19M Oct  8 14:34 ib_buf_pool_state
[yejr@localhost yejr]# file ib_buf_pool_state
ib_buf_pool_state: ASCII text
[yejr@localhost yejr]# head -2 ib_buf_pool_state
43 1344258 0 69 0 122
43 1344259 0 69 0 122
[yejr@localhost yejr]# wc ib_buf_pool_state
917439  5504634 19545127 ib_buf_pool_state

然后启动mysqld,可以看到日志中记录了大量类似下面的内容:

	....
081008 14:36:28 mysqld_safe Starting mysqld daemon with databases from /data/mysql
081008 14:36:30  InnoDB: highest supported file format is Barracuda.
081008 14:36:35 InnoDB Plugin 1.0.1 started; log sequence number 205351853106
succeeded for space=43 offset=1344258 table_id=0 69 index_id=0 122
succeeded for space=43 offset=1344259 table_id=0 69 index_id=0 122
.....

然后,再看看buffer pool的情况:

...
Buffer pool size   917503
Free buffers       0
Database pages     917503
Modified db pages  0
...

可以看到,几乎填满了所有buffer pool,相当于还原到了重启前的内存状态,省去了需要经过一段时间运行才能使内存填满所需缓冲的过程,实在是方便。不过,它也有一个致命的缺点,那就是如果你的buffer pool较大(测试时最高用到14G),则启动可能会非常慢,有时候甚至无法忍受。我的测试服务器配置应该说还算不错了(dell 2950, 16Gb ram, MD3000盘阵),然而上面的测试中,启动mysqld居然花了几乎7个小时才完成,根本无法忍受。
把buffer pool大小调成6G,还是执行上面的测试,发现启动时间立刻缩小了很多,只需要 2min53s

注意:不建议在非常重要的系统中使用该补丁,万一出了问题,没人为你负责 :)

附:下面是我的一些测试数据

417439	3m0.737s
617439	4m50.357s
637439	5m38.622s
667439	6m8.553s
717439	7m10.761s
727439	7m14.659s
827439	6h20m

第一列是表示 ib_buf_pool_state 文件中有多少行数据。另外,可以通过 head/tail/grep 等工具来自主选择需要被重新加载的buffer内容。

评论

你好! 不知道你的测试环境还在不在,希望你在做一下测试下面的情况会不会提高恢复速度(没有这么高配置的测试机)。
对dump出来的文件排序,使导入的时候减小随机读。
mv ib_buf_pool_state test
sort -n test > ib_buf_pool_state

XtraDB 最新release是支持pool buffer 的save和restore的,48G的buffer,save需要几秒,restore需要几分钟,文件大小是2.4M(page_size=16k)。