InnoDB O_DIRECT选项漫谈(一)【转】

 
最近和文件系统内核开发人员做技术交流,对O_DIRECT选项有了新的认识。
 
在 InnoDB存储引擎的配置中参数innodb_flush_method通常设置为O_DIRECT,这也是官方文档所推荐的设置值。DBA或开发人员 知道该参数是文件打开的一个标识,启用后文件的写入将绕过操作系统缓存,直接写文件。其在InnoDB存储引擎中的表现为对于写入到数据表空间将绕过操作 系统缓存。这样设置通常不会有更好的性能,但是数据库已经有自己的缓存系统,这样的设置可以确定数据库系统对于内存的使用。下面是man手册中对于 O_DIRECT选项的说明:

Try to minimize cache effects of the I/O to andfromthis file.In general this will degrade performance, but it is useful in special situations, such aswhen applications do their own caching.

然而在源码内,细心的读者可能会产生一些困惑,因为不管参数 innodb_flush_method的设置为何值,在刷新脏页时都会调用fsync操作,具体见函数buf_flush_buffered_writes。那么,当用户已经打开文件操作的O_DIRECT标识,为什么还需要进行一次fsync操作确保文件的写入呢?
 
最早发现这个问题的是Facebook的MySQL团队负责人Mark Calleghan。其在2009年时在MySQL数据库的官方论坛中提交 Bug #45892,当年看到此Bug的回复时还是有些疑惑,因为其答复的诸如xfs这类文件系统,有些元数据还需要通过fsync进行刷新。公司同事花花也有问过我同样的问题,不知道是否在做云硬盘时遇到了类似问题。
 
最近和文件系统内核开发人员做交流,其对ext4的文件系统做了简单的介绍,自己对文件系统有了重新认识,对之前Bug的回复也有了更为清楚的理解。在 有些文件系统中,例如ext4、xfs,文件(包括目录,在Linux中所有对象都是文件)都有一个inode与之对应,其保存有两部分的内容,元数据和文件的存储数据。根据 wiki的介绍,元数据包含的内容有:
  • 文件的字节数
  • 文件的权限
  • 文件的时间戳
  • 链接的数量,即有多少文件指向该inode
  • 指向数据块的链接
  • etc
可 以发现元数据及其重要的,不仅仅是文件最后修改时间、权限等信息,它还包含有指向存储块的信息。若在数据增长时,元数据没有及时更新,那么同样可能会导致 数据丢失的情况。虽然此时,数据可能在磁盘上,但文件不知道那些块也是其组成部门。可以看到,这也是MySQL官网对上述Bug中的回复:

For example,if a file grows while O_DIRECT is enabled it will still write to the new part of the file, however since the metadata doesn't reflect the new size of the file the tail portion can be lost in the event of a crash.

 
inode中的元数据是保存在inode cache中,inode的保存文件的数据是保存在操作系统缓存中(若未开启O_DIRECT标识)。读者可以观察下图Linux文件系统的实现方式:
InnoDB O_DIRECT选项漫谈(一) - insidemysql - Inside MySQL
 
fsync操作会同步上图中的Inode cache,Buffer cache(也就是操作系统缓存),Directory cache 因此这就是为什么InnoDB存储引擎即使在文件打开时加上O_DIRECT标识,刷新脏页依然需要fsync操作。这是因为O_DIRECT标识只是忽 略了图中Buffe cache。刷新文件的另一个函数fdatasync,其仅刷新buffer cache的内容到磁盘,因此比fsync有更好的性能,但是存在数据丢失的风险。
 
若用户想通过O_DIRECT写入文件,但避免可能存在的潜在风险时,可以再加上O_SYNC标识,此时写入实际变为了一个同步写( synchronous I/O) 操作,因此不再需要额外的fsync操作。见man手册中的说明:

The O_DIRECT flag on its own makes an effort to transfer data synchronously, but does not give the guarantees of the O_SYNC flag that data and necessary metadata are transferred.To guarantee synchronous I/O, O_SYNC must be used in addition to O_DIRECT.

 
未完待续......
 
MySQL5.6中增加了一个选项:O_DIRECT_NO_FSYNC
<think>好的,我现在需要帮用户解释MySQL InnoDB引擎的几个配置参数的作用。用户之前已经问过关于max_connections和back_log的问题,现在他们又向了InnoDB的配置,说明他们可能在优化数据库性能,特别是存储引擎方面的调优。 首先,用户给出的参数包括innodb_log_file_size、innodb_log_files_in_group、innodb_flush_method、innodb_io_capacity、innodb_io_capacity_max和innodb_thread_concurrency。我需要逐解释每个参数的作用,以及它们如何影响数据库性能。 innodb_log_file_size是重做日志文件的大小。重做日志对于崩溃恢复非常重要,大的日志文件可以减少磁盘I/O操作,提升写性能,但过大会增加恢复时间。用户设置为4G,这可能适用于高写入负载的环境,但需要确保文件系统有足够空间,并且备份策略能处理大的日志文件。 接下来是innodb_log_files_in_group,这指定了日志文件组中的文件数量。默认是2,用户设为3,所以总日志大小是4G*3=12G。更大的日志组可以处理更多的事务,但同样会影响恢复时间。然后是innodb_flush_method,设置为O_DIRECT。这个参数控制如何刷新数据到磁盘。O_DIRECT绕过操作系统缓存,直接写入磁盘,避免了双重缓冲,通常建议在拥有足够内存的服务器上使用,特别是使用独立存储设备时。如果用户使用的是SSD或者RAID,这个设置可以减少CPU使用,提高性能。innodb_io_capacity和innodb_io_capacity_max这两个参数与InnoDB的后台I/O活动有关。用户设置为4000和8000,因为用了SSD。传统硬盘的默认值较低,SSD需要更高的值以充分利用其高IOPS能力。正确设置这两个参数可以优化脏页刷新和插入缓冲的合并速度,避免性能瓶颈。最后是innodb_thread_concurrency,设置为0表示自动调整,允许InnoDB根据系统负载动态调整并发线程数。这对于高并发环境有利,避免手动调整的复杂性。 在解释这些参数时,需要考虑到用户的实际使用场景。他们可能在使用SSD,并且处理高并发的事务,因此这些配置都是为了最大化利用硬件性能,减少I/O等待时间,提高数据库吞吐量。同时,用户可能对数据库调优有定了解,但需要更深入的参数解释来确认配置的合理性,或者在进行性能优化时遇到问题需要调整这些参数。 此外,用户之前的问题涉及到连接数,现在向存储引擎,可能是在全面优化数据库,所以接下来的相关问题应该围绕其他InnoDB参数、日志优化、刷新机制以及硬件选择的影响等方面,帮助他们继续深入理解。</think>以下是MySQL InnoDB引擎关键配置参数的详细解释: ```ini # InnoDB引擎配置 innodb_log_file_size = 4G # 单个重做日志文件大小 innodb_log_files_in_group = 3 # 日志文件组中的文件数量 innodb_flush_method = O_DIRECT # 数据刷新方式 innodb_io_capacity = 4000 # 后台I/O操作基准吞吐量 innodb_io_capacity_max = 8000 # 最大I/O吞吐量 innodb_thread_concurrency = 0 # 并发线程数限制 ``` ### 参数详解: 1. **innodb_log_file_size**(4G) - 定义每个重做日志文件的大小 - 直接影响事务提交速度和崩溃恢复时间 - 较大值可以提升写性能但会增加恢复时间 - 建议设置为每小时产生日志量的1/4到1/2 2. **innodb_log_files_in_group**(3) - 组成重做日志组的文件数量 - 总日志大小 = 4GB * 3 = 12GB - 日志文件采用环形写入方式 - 需要与日志文件大小配合调整 3. **innodb_flush_method**(O_DIRECT) - 控制数据和日志文件的刷新方式 - O_DIRECT特点: - 绕过OS缓存直接写入存储设备 - 避免双重缓存(InnoDB缓冲池 + OS缓存) - 推荐用于独立存储设备环境 - 减少CPU使用率 4. **innodb_io_capacity**(4000) - 定义InnoDB后台任务的I/O能力基准值 - 影响: - 脏页刷新速度 - 插入缓冲合并速度 - SSD建议设置2000-4000 - 需要根据实际存储性能调整 5. **innodb_io_capacity_max**(8000) - 后台I/O操作的最大吞吐量 - 在压力较大时允许达到的峰值性能 - 通常设置为基准值的2倍 6. **innodb_thread_concurrency**(0) - 控制InnoDB内核的并发工作线程数 - 设置为0时: - 自动调整并发线程数 - 现代多核CPU建议保持默认 - 可避免手动调优的复杂性 ### 配置建议检查脚本 ```sql SHOW GLOBAL VARIABLES WHERE Variable_name IN ( 'innodb_log_file_size', 'innodb_log_files_in_group', 'innodb_flush_method', 'innodb_io_capacity', 'innodb_io_capacity_max', 'innodb_thread_concurrency' ); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值