10.5.8 优化 InnoDB 磁盘 I/O
如果您遵循最佳实践进行数据库设计,并对 SQL 操作进行了调优,但您的数据库仍然因为磁盘 I/O 活动而缓慢,考虑以下磁盘 I/O 优化措施。如果 Unix top
工具或 Windows 任务管理器显示您的工作负载的 CPU 使用百分比低于 70%,那么您的工作负载很可能是磁盘绑定的。
-
增加缓冲池大小
当表数据被缓存在
InnoDB
缓冲池中,它可以被查询重复访问而无需进行任何磁盘 I/O。使用innodb_buffer_pool_size
选项指定缓冲池的大小。这块内存区域重要到位,通常建议将innodb_buffer_pool_size
配置为系统内存的 50 到 75%。有关详细信息,请参阅 第 10.12.3.1 节,“MySQL 如何使用内存”。 -
调整刷新方法
在某些 GNU/Linux 和 Unix 版本中,使用 Unix
fsync()
调用和类似方法进行文件刷新的速度令人惊讶地慢。如果数据库写入性能是一个问题,请对innodb_flush_method
参数设置为O_DSYNC
进行基准测试。 -
配置操作系统刷新的阈值
默认情况下,当
InnoDB
创建一个新的数据文件,例如新日志文件或表空间文件时,该文件在被写入到操作系统缓存后会完全写入到磁盘,这可能导致一次性发生大量磁盘写入活动。为了强制较小的、定期刷新操作系统缓存中的数据,可以使用innodb_fsync_threshold
变量来定义一个阈值,单位为字节。当达到字节阈值时,操作系统缓存中的内容会被刷新到磁盘。默认值为 0 强制使用默认行为,即只有当文件完全写入到缓存后才刷新数据到磁盘。指定一个阈值来强制较小的、定期刷新可能对使用相同存储设备的多个 MySQL 实例有益。例如,创建一个新的 MySQL 实例及其关联的数据文件可能会导致大量磁盘写入活动,对其他使用同一存储设备的 MySQL 实例性能产生干扰。配置阈值可以帮助避免这种写入活动的峰值。
-
使用 fdatasync() 而不是 fsync()
在支持
fdatasync()
系统调用平台上,innodb_use_fdatasync
变量允许使用fdatasync()
而不是fsync()
进行操作系统刷新。一个fdatasync()
系统调用不会刷新文件元数据,除非为后续的数据检索所必需,这可能提供性能优势。innodb_flush_method
设置,如fsync
、O_DSYNC
和O_DIRECT
使用fsync()
系统调用。innodb_use_fdatasync
变量适用于使用这些设置的场景。 -
在 Linux 上使用 noop 或 deadline I/O 调度器
InnoDB
在 Linux 上使用异步 I/O 子系统 (native AIO) 对数据文件页进行读取和写入请求。这一行为由innodb_use_native_aio
配置选项控制,该选项默认启用。使用 native AIO,I/O 调度器类型对 I/O 性能有更大影响。通常,noop 和 deadline I/O 调度器是推荐的。进行基准测试以确定哪种 I/O 调度器为您的工作负载和环境提供最佳结果。有关详细信息,请参阅 第 17.8.6 节,“在 Linux 上使用异步 I/O”。 -
在 Solaris 10 x86_64 架构上使用直接 I/O
在使用
InnoDB
存储引擎时,若在 Solaris 10 上运行 x86_64 架构(AMD Opteron),请确保对InnoDB
-相关文件进行直接 I/O,以避免影响InnoDB
的性能。要为存储InnoDB
-相关文件的 UFS 文件系统启用直接 I/O,可以在挂载时使用forcedirectio
选项;请参考mount_ufs(1M)
。(Solaris 10/x86_64 的默认设置是 不 使用此选项。)若只想为InnoDB
文件操作启用直接 I/O,而不是整个文件系统,可以设置innodb_flush_method = O_DIRECT
。这样,InnoDB
将使用directio()
而不是fcntl()
进行数据文件的 I/O(但不包括日志文件)。 -
在 Solaris 2.6 或更高版本中,使用直接存储设备
当使用
InnoDB
存储引擎,并且在任何 Solaris 2.6 及以后的版本以及任何平台(sparc/x86/x64/amd64)上设置了较大的innodb_buffer_pool_size
值时,应对InnoDB
数据文件和日志文件进行基准测试。这些文件应存放在直接 I/O 的 UFS 文件系统中,并且使用forcedirectio
挂载选项(如前所述)。如果想要对日志文件也启用直接 I/O,需要设置innodb_flush_method
。VxFS 文件系统的用户应使用convosync=direct
挂载选项。不要将其他 MySQL 数据文件(如用于
MyISAM
表的数据文件)放在直接 I/O 的文件系统中。执行文件或库 必须 放在非直接 I/O 的文件系统中。 -
使用额外的存储设备
可以通过设置 RAID 配置来使用额外的存储设备。有关详细信息,请参考 第 10.12.1 节,“优化磁盘 I/O”。
或者,可以将
InnoDB
表空间数据文件和日志文件放在不同的物理磁盘上。有关更多信息,请参考以下部分: -
考虑非旋转存储设备
非旋转存储通常对随机 I/O 操作提供更好的性能;对于顺序 I/O 操作,旋转存储则更好。当在旋转和非旋转存储设备之间分配数据和日志文件时,请考虑每个文件主要进行的 I/O 类型。
随机 I/O 操作倾向于使用 文件-表 和 通用表空间 数据文件、回滚表空间 文件和 临时表空间 文件。顺序 I/O 操作倾向于使用
InnoDB
系统表空间 文件、双写文件和日志文件,如 二进制日志 和 重做日志 文件。在使用非旋转存储设备时,请审查以下配置选项的设置:
-
使用
crc32
选项的快速校验和算法,适用于高速存储系统。 -
针对旋转存储设备优化 I/O。对于非旋转存储或旋转和非旋转存储的混合使用,请禁用它,默认情况下已禁用。
-
允许在空闲期间设置页面刷新的限制,这可以帮助延长非旋转存储设备的寿命。
-
默认设置为10000通常就足够了。
-
默认值为(2 *
innodb_io_capacity
)适用于大多数工作负载。 -
如果redo日志存储在非旋转式存储设备上,考虑禁用此选项以减少日志记录。请参阅禁用压缩页面的日志记录。
-
innodb_log_file_size
(已弃用)如果redo日志存储在非旋转式存储设备上,请配置此选项以最大化缓冲和写组合。
-
如果redo日志存储在非旋转式存储设备上,请配置此选项以最大化缓冲和写组合。
-
考虑使用与磁盘内部扇区大小相匹配的页面大小。早期一代SSD设备通常有4KB的扇区大小。一些新型号设备有16KB的扇区大小。默认的
InnoDB
页面大小为16KB。将页面大小保持接近存储设备块大小可以减少未改变数据被重写到磁盘的数量。 -
如果二进制日志存储在非旋转式存储设备上且所有表都有主键,考虑将此选项设置为
minimal
以减少日志记录。
确保TRIM支持已启用于您的操作系统。通常情况下,它是默认启用的状态。
-
-
增加I/O容量以避免延迟
如果通过
InnoDB
的检查点操作导致吞吐量下降,请考虑增加innodb_io_capacity
配置选项的值。更高的值会导致更多的刷新操作,从而避免工作量积压,导致吞吐量下降。 -
如果系统未落后于
InnoDB
的刷新操作,请考虑降低innodb_io_capacity
配置选项的值。通常情况下,您会将此选项值设置得尽可能低,但不至于导致周期性吞吐量下降,如前所述。在典型场景中,如果您可以降低该选项值,您可能会在SHOW ENGINE INNODB STATUS
的输出中看到类似的组合:历史列表长度低,低于几千。
-
插入缓冲区合并接近行被插入。
-
修改页在缓冲池中一致性地低于
innodb_max_dirty_pages_pct
缓冲池的百分比。(在服务器不进行大规模插入时测量;在大规模插入期间,修改页百分比通常会显著上升。) -
Log sequence number - Last checkpoint
小于或等于日志文件总大小的7/8或理想情况下小于6/8。 -
将系统表空间文件存储在Fusion-io设备上
-
-
您可以利用一个与双写缓冲相关的I/O优化,通过将包含双写存储区域的文件存储在支持原子写入的Fusion-io设备上。(双写存储区域位于双写文件中。请参阅第17.6.4节,“Doublewrite Buffer”。)当双写存储区域文件存储在支持原子写入的Fusion-io设备上时,双写缓冲会自动禁用,并使用Fusion-io原子写入对所有数据文件进行操作。这一特性仅适用于Fusion-io硬件,并且仅在Linux上的Fusion-io NVMFS上可用。为了充分利用这一特性,请设置
innodb_flush_method
为O_DIRECT
。由于双写缓冲设置是全局的,双写缓冲也会对不在Fusion-io硬件上的数据文件禁用。
-
Disable logging of compressed pages
当使用
InnoDB
表的压缩特性时,修改压缩数据后的图片会被写入到重做日志中。这一行为由innodb_log_compressed_pages
控制,默认情况下启用,以防止在恢复过程中由于不同版本的zlib压缩算法使用而导致的损坏。如果您确定zlib版本不会发生变化,可以禁用innodb_log_compressed_pages
来减少工作负载中修改压缩数据的重做日志生成量。