这两天是O’Reilly MySQL Conference & Expo,期间有很多关于MySQL的相关话题的介绍,包括MySQL、PBXT、Drizzle、MariaDB、XtraDB等等,不过最抢风头的应该是InnoDB1.0.7GA(with MySQL-5.5)的新特性,回头想想,Oracle/InnoDB也酝酿了很久的吧。
无论如何,这些新特性中最吸引我的是InnoDB的Faster Recovery。
一般地,MySQL/InnoDB都是运行在普通的PC Server + Linux(Unix),虽然不期待小型机+AIX的高可用,但想尽一切办法缩短MySQL的不可用时间,仍然是DBA的目标。根据经验,主机OS崩溃、硬件故障,仍然是影响MySQL可用性的最主要因素,当这些故障(OS、硬件)恢复后,另一个非常耗时的恢复就是InnoDB自己的恢复时间。一般主机发生一次重启,正常大约<5分钟,而这时InnoDB恢复可能需要40分钟或者更久(这依赖于Buffer Pool、脏页面比例、TPS等因素)。
试想,如果每次能够把故障时间控制在10分钟之内,那么通过应用容错、Cache支持等办法,用户体验和可用时间都将有进一步的提升。
这次Plugin1.0.7GA通过算法和内存管理上的改进,将恢复时间大大缩短。
实验:
在InnoDB Blog中,给出了一个测试:Plugin1.0.6花费7小时38分钟恢复的过程,使用Plugin1.0.7则仅仅花了13分56秒,总共快了32倍,其中扫描Redo阶段快了16倍,应用日志阶段快了35倍。(实验中Buffer Pool是18G)
现在,MySQL-5.5.4-m3自带的是InnoDB-1.1,也可以自己测试一下。
root@(none) 05:33:03>select version(),@@innodb_version; +--------------+------------------+ | version() | @@innodb_version | +--------------+------------------+ | 5.5.4-m3-log | 1.1.0 | +--------------+------------------+
原理:
崩溃恢复(Crash recovery)可以看成两个阶段,第一阶段称为扫描重做日志(Redo scan),这时InnoDB读取磁盘上的Redo Log,并将其存放到一个Hash表中;第二阶段应用这些Redo Log,将这些日志应用到Data Page上。
在将Redo Log读取到Buffer Pool的Hash表的过程中,InnoDB在需要的时候分配16K的Block用来存储这个这些Redo。为了确保Buffer Pool中有足够剩余空间来存储数据页(Data Page),这样如果Redo很大的话,这个Block heap也会很大。这里InnoDB做了一件很2的事情,每次读取一个Redo的时候,都会遍历一次前面的Heap来确保,没有占用太多的空间。所以,如果崩溃前InnoDB的Buffer Pool很大,Dirty Page很多,这个Heap可能很大,每次遍历就会大大降低恢复时的效率。
InnoDB通过给这个Heap增加一个header来存储这些信息,解决了上面的问题。
恢复过程中,另一个耗时的操作是发生在应用Redo的阶段。每一个应用了Redo Log的Data Page都会被放到一个叫Flush_list的链表中等待Flush,而这个链表中的Data Page是严格安装其LSN顺序排列的,在InnoDB正常工作的时候,这总是没有问题的,因为Data Page的LSN值总是单调增加的。但是在恢复阶段,InnoDB则需要不断的扫描这整个链表来确定一个Data Page的位置。
这个问题由来已久(Bug,Improving InnoDB recovery time),最终,在社区给出Patch之后,InnoDB终于修复了这个问题。
InnoDB在恢复阶段,通过一棵辅助的红黑树(Red-Black Tree)来存储这些Page,借此来避免单纯的扫描。在恢复阶段结束后,这棵红黑树将被删除,Flush_list仍然保持原来的结构。
最后:
如果这个特性稳定,那么,以后Buffer Pool就可以更放心的调大些了。
参考文献:
Leave a Reply