MySQL根据5.1.34之前版本的一个BUG分析O_DIRECT

Mysql错误日志:

Version:  '5.1.34-percona-highperf-log'  socket:  '/home/mysql/mysql.sock'  port:  3306  Source distribution
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_191_0.ibd: CREATE: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_191_0.ibd: OPEN: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_192_0.ibd: CREATE: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662
140324  5:00:02  InnoDB: Failed to set O_DIRECT on file  /tmp/#sql593e_192_0.ibd: OPEN: Invalid argument, continuing anyway
140324  5:00:02  InnoDB: O_DIRECT is known to result in  'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662

innodb_flush_method 这个参数控制着innodb数据文件及redo log的打开、刷写模式。对于这个参数,文档上是这样描述的:

从MySQL 5.6的版本开始,也就是InnoDB 1.2版本中(PS:MariaDB 10.x版本将集成InnoDB 1.2版本),对于参数innodb_flush_method提供了一个新的设置值O_DIRECT_NO_FSYNC。

有四个值:fdatasync,O_DSYNC,O_DIRECT,O_DIRECT_NO_FSYNC

  • 默认是fdatasync,调用fsync()去刷数据文件与redo log的buffer
  • 为O_DSYNC时,innodb会使用O_SYNC方式打开和刷写redo log,使用fsync()刷写数据文件
  • 为O_DIRECT时,innodb使用O_DIRECT打开数据文件,使用fsync()刷写数据文件跟redo log
  • 为O_DIRECT_NO_FSYNC时,InnoDB存储引擎将依然使用O_DIRECT选项打开数据表空间文件,但是在刷新时,不再需要需要额外的fsync操作

首先文件的写操作包括三步:open,write,flush

  • 上面最常提到的fsync(int fd)函数,该函数作用是flush时将与fd文件描述符所指文件有关的buffer刷写到磁盘,并且flush完元数据信息(比如修改日期、创建日期等)才算flush成功。
  • 使用O_SYNC方式打开redo文件表示当write日志时,数据都write到磁盘,并且元数据也需要更新,才返回成功
  • O_DIRECT则表示我们的write操作是从mysql innodb buffer里直接向磁盘上写

至此总结一下三者写数据方式:

  • fdatasync模式:写数据时,write这一步并不需要真正写到磁盘才算完成(可能写入到操作系统buffer中就会返回完成),真正完成是flush操作,buffer交给操作系统去flush,并且文件的元数据信息也都需要更新到磁盘。
  • O_DSYNC模式:写日志操作是在write这步完成,而数据文件的写入是在flush这步通过fsync完成
  • O_DIRECT模式:数据文件的写入操作是直接从mysql innodb buffer到磁盘的,并不用通过操作系统的缓冲,而真正的完成也是在flush这步,日志还是要经过OS缓冲

优点:

  1. 目前都是硬盘如SSD、F/M卡 IO已经很快了,无需再利用系统缓存。
  2. 最为安全和稳妥的做法还是将参数innodb_flush_method设置为O_DIRECT。
  3. 若重做日志使用O_DIRECT,写入重做日志文件的过程会变慢(因为不是仅写入到操作系统缓存),Group Commit的效率就会变差。

原文发布于微信公众号 - MYSQL轻松学(learnmysql)

原文发表时间:2016-10-25

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏开源优测

性能测试必备监控技能jvm之jdk命令行工具篇16

前言 对于JVM的性能监控,主要注意以下关键参数,通过jdk自带的命令行工具,即可查看相关参数,从而分析系统或目标服务程序中存在的性能瓶颈 jps JVM Pr...

26312
来自专栏前端小叙

前端如何获取http状态码400的返回值

axios.get("/check_mobile_and_sent_code",{withCredentials:true,params:{mobile:for...

3468
来自专栏乐沙弥的世界

Oracle 参数文件

主要用来记录数据库的配置文件,在数据库启动时,Oracle读取参数文件,并根据参数文件中的参数设置来配置数据库。

621
来自专栏杂烩

redis拾遗 原

    自己边学边记录的,写在了excel里,这里直接沾出来,懒得美化加工了。

992
来自专栏Snova云数仓

Greenplum中对表批量授权

  DBA在管理数据仓库的时候,往往会创建多个帐号,每个帐号有不同的用途。因此这里就有不同帐号间表授权的需求。

1314
来自专栏WindCoder

《Linux内核分析》之触发一个系统调用实验总结

系统调用列表中可用的很多,可惜对用代码进行系统调用不太清楚,只好从网上窃取了一份,地址在最后放上。此处以fork()为例。

533
来自专栏岑玉海

hadoop 参数

看《Hadoop:权威指南》的时候收集了书上写的一些需要优化的参数,记录了一下子,给大家分享一下吧。 1.mapred.task.timeout ...

3424
来自专栏文渊之博

具体问题解决:分离脚本

有时候需要从一个服务器转移数据库到另一个。如果打算一下子分离所有数据库,那么下面的脚本就是有用了。 生成分离脚本: SELECT DISTINCT 'use m...

1828
来自专栏杨建荣的学习笔记

用shell帮助解决ORA问题

今天碰到一个设计的严重问题,由于使用了外部文件来和sqlplus交互 sql大体结构如下 select xxxxx from xxxxx where table...

2795
来自专栏Jackson0714

【T-SQL性能优化】01.TempDB的使用和性能问题

33813

扫码关注云+社区