考虑下面的一个场景,如下图所示:

对于存在时间比较长,变更又比较多的大表,除非我们对于这个表进行重建,否则leaf page的离散性会随着时间的推移,越来越严重。但对于在线应用来说,重建又会产生比较大的运维风险,这里就介绍一种平衡的方法,logical read-ahead。

逻辑预读的概念是指,根据branch节点来预读leaf节点。

  1. 一个cursor定位到leaf page,然后根据leaf page之间的双链表,moves_up进行扫描数据;
  2. 另一个cursor定位到branch节点,因为InnoDB B-Tree结构的每一层都由双向链表进行连接,然后这个cursor就沿着branch节点进行扫描,保存扫描到的page_no,然后使用异步IO,发起这些leaf page的预读取。

MySQL 5.6版本上的实现方式:

  1. branch节点扫描的cursor保存到trx结构中,生命周期到一个sql语句结束;
  2. branch cursor扫描用户可配置的page count,临时保存到数组中,对page_no进行排序;

logical read-ahead很好的提升了离散存储数据的吞吐能力,Facebook在他们的MySQL实例的逻辑备份过程中,对于大表的dump备份开启了此特性,备份速度有非常大的提升。