日期:2014-05-16  浏览次数:20461 次

mysql innodb恢复时间长的问题
mysql innodb中,还是存在当恢复recovery故障后,时间很长的问题,查了下,原来原因如下:
当故障发生,重新启服务后,会自动完成恢复操作,将数据库恢复到之前一个正常状态。恢复进程会完成两步,第一步:检查redo日志,将之前完成并提交的事务全部重做;第二步:将undo日志中,未完成提交的事务,全部取消。那么,就仅仅做了这么两步为什么恢复过程会变得如此漫长呢?在InnoDB未对恢复速度做提升之前,MySQL的bug列表中,曾被提出了两个改进请求:Bug #29847和Bug #49535。

“民间办法”— 治标不治本

方法1:重启mysqld之前,暂时减小innodb_buffer_pool_size的大小,将innodb_flush_method=O_DIRECT临时注释掉,会缩短故障恢复的时间。

方法2:一开始就把my.cnf中参数innodb_log_file_size的大小设置的小些,该选项与恢复时间的长短有直接关系,但太小也会对性能造成影响。

“专业解决” — 改进代码

Bug #49535提到,在恢复期间重做redo日志时,检查可用内存的大小将消耗超过90%的CPU。恢复redo日志时,会在buffer pool中开辟一块空间,用来的将redo log从磁盘中读到内存当中,放到一个hash table里面,随着读出redo log的增加,这个hash table会不断增大,为了保证该空间不超过buffer pool的大小,所以,每读入一次redo log都要去遍历一遍hash table来获得其大小,显然效率低下而且很耗资源。解决办法是在hash table的结构中加入一个头字段来单独记录总的大小。

Bug #29847是由flush list过大导致。当每执行一条日志后,都会被插入到一个叫作flush list的列表中,也就是我们说的dirty page列表,正常情况下有跟新完成,那么新的跟新会被放到列表的前面,而当发生恢复时,每次跟新的记录都会按照之前LRU的顺序放到原来的位置,同时,不幸的是这个flush list又是一个古老的链表结构,每次插入的遍历痛苦,你懂得!flush list变的越长将消耗的时间就越久,所以,为什么之前提到,减小innodb_log_file_size的大小,能有效的缩短恢复时间,其实,是为了减少flush list的大小。解决办法是采用一种叫做红黑树(red-black tree)的数据结构,这个我还没有看明白:) 在pluin 1.0.7以后就没有恢复太久的问题了,为了提高性能完全可以尽可能的加大redo log的设置,InnoDB也保证了不会再有超长恢复等待的发生。