随着存储设备越来越快,InnoDB许多原有的设计不再适合新的高速硬件,因此MariaDB 10.1 Alpha版本针对FusionIO PCI-E SSD做出了专门的优化,充分利用了Fio的硬件特性。 MDEV-6246这个需求改造了MariaDB,以利用fio的Atomic writes和文件系统压缩特性。

    为何Fio会更快呢,因为传统的存储设备读取,是左图的方式,要经过RAID控制器,来回的路径就长了。而Fio才有右图的方式,设备通过PCI槽直接与CPU交互,大大缩短了路径。

    Atomic writes

    InnoDB一直存在一个叫做Double Write Buffer的东西,目的就是为了防止页面写到一半系统崩溃,导致页面损坏,因为InnoDB的Page是16K,而一般的机械硬盘扇区是512字节,SSD大都是4K的块大小,都不能保证16K的写入是完整的。 而Fio的NVMFS文件系统则提供了原子写的保证,只要对文件句柄增加DFS_IOCTL_ATOMIC_WRITE_SET的ioctl标记位,就可以启用这个文件的原子写支持。

      这样一来Double Write Buffer就没有存在的价值了,因为不会出现部分写,每个write下去都可以保证所写内容全部完成,这可以相当程度上提升InnoDB的性能。

      Page compression

      InnoDB标准的页面大小是16K,InnoDB也提供1K、2K、4K、8K的压缩页面大小,通过KEY_BLOCK_SIZE来设置压缩大小,使用zlib标准库来进行压缩。 但是Page是频繁被更新的,如果每次修改都重新压缩页面,代价很高,InnoDB就采用了modification log来暂存部分修改信息,而避免了频繁解压缩,待modification log存满时,再重新对整个Page做一次重构压缩。 但是Compressed Page载入InnoDB Buffer Pool时,InnoDB只能处理未压缩的页面,因此还要在内存中存一份解压页面,回写到磁盘时再次压缩。

      总而言之,InnoDB的Compressed Page有这些缺点:

      1. 内存开销
      2. 空间: 压缩和解压缩页面都要存在InnoDB Buffer Pool
      3. 访问: 修改需要同时写入到压缩页面和未压缩页面
      4. 软件压缩库zlib (从磁盘读取时需要解压缩放入内存, 页面分裂时需要重新压缩)
      5. Split & Recompress & Rebalance when mlog overflows
      6. 空间收益
      7. Modification logPage预留空间弱化了压缩带来的空间缩减
      8. 糟糕的实现
      9. 代码过于复杂而导致压缩和未压缩的表性能差距非常明显

      MariaDB与FusionIO合作利用NVMFS文件系统的特性,修改InnoDB的Page结构来支持文件系统级的压缩。 Page compression要求InnoDB做了如下配置:

        当页面被读取时,会在放入Buffer Pool之前进行解压缩,将原始页面载入内存。因此需要在文件头中加入一个新的Page type:FIL_PAGE_PAGE_COMPRESSED page.jpeg

        综合起来可以这样定义一张表:

        意思是将t3表存到/dev/fioa盘,开启Page compression,采用4级压缩,开启原子写。

        经过测试,可以看出,LZ4的压缩比例最好,而且,对性能影响非常小。