InnoDB O_DIRECT选项漫谈(二)

前一篇 中已经解释了InnoDB存储引擎为什么即使在开启O_DIRECT选项后依然需要调用fsync操作。本篇将说明MySQL 5.6中InnoDB存储引擎的变化以及O_DIRECT对重做日志文件的影响。

从MySQL 5.6的版本开始,也就是InnoDB 1.2版本中(PS:MariaDB 10.x版本将集成InnoDB 1.2版本),对于参数innodb_flush_method提供了一个新的设置值 O_DIRECT_NO_FSYNC。在该参数设置下,InnoDB存储引擎将依然使用O_DIRECT选项打开数据表空间文件,但是在刷新时,不再需要需要额外的fsync操作。见官方手册中的说明:

An alternative setting is O_DIRECT_NO_FSYNC: it uses the O_DIRECT flag during flushing I/O, but skips thefsync() system call afterwards. This setting is suitable for some types of filesystems but not others. For example, it is not suitable for XFS. If you are not sure whether the filesystem you use requires anfsync(), for example to preserve all file metadata, use O_DIRECT instead.

然而,官方仅说明使用xfs文件系统不能设置为 O_DIRECT_NO_FSYNC,但却只字未提哪个文件系统可以设置?请问MySQL官方这样的说明又有何意义呢?reiserfs和btrfs貌似(不十分确定)不使用inode来存放元数据信息,或许这两个文件系统下可以进行O_DIRECT_NO_FSYNC的设置?这个问题留给文件系统专家来回答了 InnoDB O_DIRECT选项漫谈(二) - insidemysql - Inside MySQL 。不过目前看来,最为安全和稳妥的做法还是将参数innodb_flush_method设置为O_DIRECT。

继续深入思考一个问题,为什么InnoDB的重做日志不使用O_DIRECT标识进行打开,而依然使用buffered I/O呢?我的理解是为了更为有效的 Group Commit。若深入源码内部来看事务提交时的操作,InnoDB存储引擎的处理方式:

lock log -> mutex
copy last redo log block to a new block 
write redo log buffer to disk
unlock log -> mutex
fsync redo log files

可以看到fsync操作是在释放log->mutex之后。 这样做的目的是在fsync时,由于已经释放log->mutex,那么其他事务可以继续将重做日志条目写入到redo log buffer中, 同时这也是为什么在事务提交时,InnoDB会拷贝最后一个redo log block。若重做日志使用O_DIRECT,写入重做日志文件的过程会变慢(因为不是仅写入到操作系统缓存),Group Commit的效率就会变差。

Mark Callaghan尝试过以O_DIRECT的方式打开重做日志( http://www.facebook.com/note.php?note_id=10150219759210933 ),结果如下所示:

Results for all_direct are better at low-concurrency and O_DIRECT is faster for 4 or more concurrent connections.

   1       2       4       8      16      32      64    128

1952    2777    3530    3755    3829    3741    3760    3803  all_direct

1608    2479    3507    4541    4550    4644    4698    4581  O_DIRECT

Mark Callaghan只是给出了测试的结果,但是并没有说明问题的原因。根据Mark的测试环境,我想这就是因为Group Commit效率问题所致。Percona版本提供了ALL_O_DIRECT来设置重做日志的打开标识,但是根据我的研究,这是没有必要的,用户也不需要过于迷信该参数。

MySQL 5.6开始InnoDB可以将重做日志文件组设置为最大512G,之前的限制为4G。这对SSD和写入密集型应用会带来明显的帮助。但是重做日志buffered I/O的问题是会导致使用过多的操作系统缓存,这也是为什么Mark会想到使用O_DIRECT的方式来打开重做日志。

既然不能在InnoDB内部处理该问题(至少目前),我想可以通过操作系统提供的接口来刷新操作系统中缓存的数据,从而减少内存过度的使用问题。例如:

sysctl -w vm.drop_caches = 3

关于O_DIRECT的话题暂时结束了,希望用户能更好的理解其对InnoDB内部的影响。后续我将继续关注 O_DIRECT_NO_FSYNC对于其他文件系统的影响。

-- EOF --


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值