使用tmpfs文件系统做MySQL tmpdir潜在的问题


在前面我写过一篇关于tmpfs和ramfs对比分析的文章()。当初也是因为看到有人用/dev/shm(tmpfs)做MySQL tmpdir,于是就去学习了下tmpfs。今天再次谈这个问题是因为使用tmpfs做MySQL tmpdir(以后简称tmpdir)确实还是存在一些问题的,而且在某些特定的Linux 内核版本还会触发bug。今天写篇文章记录一下。

当时的机器环境信息: 

[bosen@localhost ~]$ uname -a
Linux localhost.localdomain 2.6.18-164.el5 #1 SMP Thu Sep 3 03:28:30 EDT 2009 x86_64 x86_64 x86_64 GNU/Linux
[bosen@localhost ~]$ cat /etc/RedHat-release
CentOS release 5.4 (Final) 

bug信息(MySQL-5.5.30社区版): 

130305 16:05:16 InnoDB: Error: Linux Native AIO is not supported on tmpdir.
InnoDB: You can either move tmpdir to a file system that supports native AIO
InnoDB: or you can set innodb_use_native_aio to FALSE to avoid this message.
130305 16:05:16 InnoDB: Error: Linux Native AIO check on tmpdir returned error[22]
130305 16:05:16 InnoDB: Warning: Linux Native AIO disabled.   我们可以看到在启动MySQL 实例的时候报tmpdir上不支持Linux Native AIO(tmpdir是放在/dev/shm,它是Linux上必须存在的挂载点,为tmpfs文件系统)。然后就显示的将innodb_use_native_aio关闭了。在bug list上搜索了一下这个问题确实2010年就有人提出来了,也是在CentOS上触发的,原因就是因为某些版本的内核不支持tmpfs上的Linux Native AIO。这个没得多解释为什么,我也不清楚为什么某些内核版本不支持。那么官方是怎么修复这个bug的呢?其实官方也没有真正意义上进行修复,它仅仅是在启动MySQL实例时对将来可能需要用到tmpfs的地方做检测,如果它不支持AIO那么就显示的将innodb_use_native_aio关闭(因为整个MySQL中只有innodb用到了AIO,所以只需这个参数关闭即可),所以在前面我们看到的现象就是官方修复后的结果,也就是说5.5.30这个版本已经修复这个bug了。   那么对于没有修复的版本会存在什么问题呢?其实理论上不会出现问题,因为我们一般用到tmpfs也只可能将其用在tmpdir上,那么它的触发条件就比较特殊:必须是innodb+temporary table才可能触发。为什是这两个条件?

条件1:innodb,因为只有innodb才支持AIO特性,因此这是条件之一。条件2:temporary table。因为我们仅仅在tmpdir上使用到了临时表所以必须得有使用到tmpdir的地方,那就是临时表了。那么你认为你们线上会创建innodb类型的临时表吗?至少我没找到理由要这么做。临时表分两种,显式和隐式,create temporary这是显式临时表,绝大部分都会创建为memory类型;MySQL内部运行过程中创建的临时表叫隐式临时表,比如一个SQL查询,比如表结构变更、比如load data infile。而默认的情况下隐式临时表都是memory类型,当超出参数设定值后就会自动转换为myisam类型,所以也用不到innodb。

所以我说一般这个bug不会出现,从某种角度来说这个bug没修复也是件好事,因为修复之后如果要继续使用tmpfs做为tmpdir,而一旦tmpfs不支持AIO,那么innodb_use_native_aio会被关闭,但AIO对于IO密集型应用来说性能有一定的提升,具体数据应该是tps提升15%左右,当然这与底层存储设备、IO线程数都有关系,所以这个数值并不会一定准确,但是可以肯定的是性能不会下降。

但即使这个bug永远不会触发,使用tmpfs做tmpdir还是会存在一些问题的,前面说了DDL、load data infile会使用tmpdir,而这些操作需要的临时表空间是很大的,如果使用tmpfs很有可能瞬间对内存的冲击很大,导致系统抖动、swap大量使用等等从而造成性能影响。所以建议线上还是不要使用tmpfs较好。

最后再介绍一个跟tmpfs相关的bug,也是在这次测试时发现的,当然就显得更加不重要了。前面测试tmpfs不支持AIO这个bug时用的是5.5.30版本,为了测试公司内部的5.5.12是否存在相同的问题,于是也做了同样的测试 create temporary table tmp(a int)engine=innodb ,结果error log中有如下信息:

130306 10:46:51 InnoDB: O_DIRECT is known to result in 'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
130306 10:46:51 InnoDB: Failed to set O_DIRECT on file /dev/shm/#sql26a1_1_0.ibd: OPEN: Invalid argument, continuing anyway
130306 10:46:51 InnoDB: O_DIRECT is known to result in 'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
130306 10:46:52 InnoDB: Operating system error number 22 in a file operation.
InnoDB: Error number 22 means 'Invalid argument'.
InnoDB: Some operating system error numbers are described at
InnoDB: http://dev.mysql.com/doc/refman/5.5/en/operating-system-error-codes.html
InnoDB: File name /dev/shm/#sql26a1_1_0.ibd

这个bug很明显tmpfs上不支持在open的时候加O_DIRECT参数,原理是什么呢?根据个人理解,我觉得是因为tmpfs采用vm实现,就是page cache那层(参见tempfs和ramfs对比分析那篇文章里面说的tmpfs与ramfs性能比较那段),而O_DIRECT的目的就是绕过page cache这层,所以tmpfs不支持O_DIRECT自然也就是情理之中了。

之前一直认为使用tmpfs做tmpdir会加速大临时表速度,觉得如果内存充足是个不错的选择,看来还是会存在很多问题。所以很多东西还是要多测试、多思考,当然还要对底层很多原理性的东西有一定了解,这样才能更好的解决问题。

相关内容

    暂无相关文章