欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

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

程序员文章站 2022-05-24 15:02:44
...

当初也是因为看到有人用/dev/shm(tmpfs)做MySQL tmpdir,于是就去学习了下tmpfs。今天再次谈这个问题是因为使用tmpfs做MySQL tmp

在前面我写过一篇关于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:
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会加速大临时表速度,觉得如果内存充足是个不错的选择,看来还是会存在很多问题。所以很多东西还是要多测试、多思考,当然还要对底层很多原理性的东西有一定了解,这样才能更好的解决问题。

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