### 8.5.8 优化 InnoDB 磁盘 I/O

[](<>)[](<>)[](<>)[](<>)

如果您遵循 SQL 操作的数据库设计和调优技术的最佳实践，但由于磁盘 I/O 活动繁重，您的数据库仍然很慢，请考虑这些磁盘 I/O 优化。如果 Unix`最佳`工具或 Windows 任务管理器显示您的工作负载的 CPU 使用率低于 70%，您的工作负载可能是磁盘绑定的。

-   增加缓冲池大小

    当表数据缓存在`InnoDB`缓冲池，它可以被查询重复访问，而不需要任何磁盘 I/O。指定缓冲池的大小[`innodb_buffer_pool_size`](innodb-parameters.html#sysvar_innodb_buffer_pool_size)选项。此内存区域非常重要，因此通常建议[`innodb_buffer_pool_size`](innodb-parameters.html#sysvar_innodb_buffer_pool_size)配置为系统内存的 50% 到 75%。有关更多信息，请参阅，[第 8.12.3.1 节，“MySQL 如何使用内存”](memory-use.html).

-   调整冲洗方式

    在某些版本的 GNU/Linux 和 Unix 中，使用 Unix 将文件刷新到磁盘`同步（）`调用（其中`InnoDB`默认情况下使用）和类似的方法非常慢。如果数据库写入性能是一个问题，请使用[`innodb_flush_method`](innodb-parameters.html#sysvar_innodb_flush_method)参数设置为`O_DSYNC`.

-   配置操作系统刷新的阈值

    默认情况下，当`InnoDB`创建一个新的数据文件，例如新的日志文件或表空间文件，该文件在刷新到磁盘之前已完全写入操作系统缓存，这可能会导致一次发生大量磁盘写入活动。要强制从操作系统缓存中定期刷新较小的数据，您可以使用[`innodb_fsync_threshold`](innodb-parameters.html#sysvar_innodb_fsync_threshold)用于定义阈值的变量，以字节为单位。当达到字节阈值时，操作系统缓存的内容被刷新到磁盘。默认值 0 强制执行默认行为，即仅在文件完全写入缓存后才将数据刷新到磁盘。

    在多个 MySQL 实例使用相同的存储设备的情况下，指定阈值以强制进行较小的定期刷新可能是有益的。例如，创建新的 MySQL 实例及其关联的数据文件可能会导致磁盘写入活动激增，从而阻碍使用相同存储设备的其他 MySQL 实例的性能。配置阈值有助于避免写入活动的此类激增。

-   使用 fdatasync() 而不是 fsync()

    在支持的平台上`数据同步（）`系统调用，[`innodb_use_fdatasync`](innodb-parameters.html#sysvar_innodb_use_fdatasync)MySQL 8.0.26 中引入的变量允许使用`数据同步（）`代替`同步（）`用于操作系统刷新。一个`数据同步（）`除非后续数据检索需要，否则系统调用不会刷新对文件元数据的更改，从而提供潜在的性能优势。

    的一个子集[`innodb_flush_method`](innodb-parameters.html#sysvar_innodb_flush_method)设置如`同步`,`O_DSYNC`， 和`O_DIRECT`采用`同步（）`系统调用。这[`innodb_use_fdatasync`](innodb-parameters.html#sysvar_innodb_use_fdatasync)变量在使用这些设置时适用。

-   在 Linux 上使用带有本机 AIO 的 noop 或截止时间 I/O 调度程序

    `InnoDB`使用 Linux 上的异​​步 I/O 子系统（原生 AIO）来执行数据文件页面的预读和写请求。这种行为是由控制[`innodb_use_native_aio`](innodb-parameters.html#sysvar_innodb_use_native_aio)配置选项，默认启用。使用原生 AIO，I/O 调度器的类型对 I/O 性能的影响更大。一般来说，推荐使用 noop 和deadline I/O 调度器。执行基准测试以确定哪个 I/O 调度程序为您的工作负载和环境提供最佳结果。有关详细信息，请参阅[第 15.8.6 节，“在 Linux 上使用异步 I/O”](innodb-linux-native-aio.html).

-   在 Solaris 10 for x86 上使用直接 I/O_64架构

    使用时`InnoDB`Solaris 10 for x86 上的存储引擎\_64 架构（AMD Opteron），使用直接 I/O`InnoDB`- 相关文件，以避免降级`InnoDB`表现。对用于存储的整个 UFS 文件系统使用直接 I/O`InnoDB`-related 文件，使用`强制方向`选项;看`mount_ufs(1M)`.（Solaris 10/x86 上的默认设置\_64 是*不是*使用此选项。）仅将直接 I/O 应用于`InnoDB`文件操作而不是整个文件系统，设置[`innodb_flush_method = O_DIRECT`](innodb-parameters.html#sysvar_innodb_flush_method).有了这个设置，`InnoDB`来电`方向（）`代替`fcntl()`用于 I/O 到数据文件（不适用于 I/O 到日志文件）。

-   对 Solaris 2.6 或更高版本的数据和日志文件使用原始存储

    使用时`InnoDB`大容量存储引擎[`innodb_buffer_pool_size`](innodb-parameters.html#sysvar_innodb_buffer_pool_size)在任何 Solaris 2.6 及更高版本和任何平台 (sparc/x86/x64/amd64) 上的价值，使用`InnoDB`原始设备或单独的直接 I/O UFS 文件系统上的数据文件和日志文件，使用`强制方向`安装选项如前所述。（必须使用挂载选项而不是设置[`innodb_flush_method`](innodb-parameters.html#sysvar_innodb_flush_method)如果您想要日志文件的直接 I/O。） Veritas 文件系统 VxFS 的用户应使用`convosync=直接`挂载选项。

    不要放置其他 MySQL 数据文件，例如用于`MyISAM`表，在直接 I/O 文件系统上。可执行文件或库*禁止*放置在直接 I/O 文件系统上。

-   使用额外的存储设备

    额外的存储设备可用于设置 RAID 配置。有关相关信息，请参阅[第 8.12.1 节，“优化磁盘 I/O”](disk-issues.html).

    或者，`InnoDB`表空间数据文件和日志文件可以放在不同的物理磁盘上。有关详细信息，请参阅以下部分：

    -   [第 15.8.1 节，“InnoDB 启动配置”](innodb-init-startup-configuration.html)

    -   [第 15.6.1.2 节，“在外部创建表”](innodb-create-table-external.html)

    -   [创建通用表空间](general-tablespaces.html#general-tablespaces-creating)

    -   [第 15.6.1.4 节，“移动或复制 InnoDB 表”](innodb-migration.html)

-   考虑非旋转存储

    非循环存储通常为随机 I/O 操作提供更好的性能；和用于顺序 I/O 操作的旋转存储。在旋转和非旋转存储设备上分发数据和日志文件时，请考虑主要在每个文件上执行的 I/O 操作的类型。

    面向随机 I/O 的文件通常包括[每表文件](glossary.html#glos_file_per_table)和[通用表空间](glossary.html#glos_general_tablespace)数据文件，[撤消表空间](glossary.html#glos_undo_tablespace)文件，以及[临时表空间](glossary.html#glos_temporary_tablespace)文件。面向顺序 I/O 的文件包括`InnoDB` [系统表空间](glossary.html#glos_system_tablespace)文件（由于[双写缓冲](glossary.html#glos_doublewrite_buffer)在 MySQL 8.0.20 之前和[变化缓冲](glossary.html#glos_change_buffer))、MySQL 8.0.20 中引入的双写文件，以及日志文件如[二进制日志](glossary.html#glos_binary_log)文件和[重做日志](glossary.html#glos_redo_log)文件。

    使用非旋转存储时查看以下配置选项的设置：

    -   [`innodb_checksum_algorithm`](innodb-parameters.html#sysvar_innodb_checksum_algorithm)

        这`crc32`选项使用更快的校验和算法，推荐用于快速存储系统。

    -   [`innodb_flush_neighbors`](innodb-parameters.html#sysvar_innodb_flush_neighbors)

        优化旋转存储设备的 I/O。为非旋转存储或旋转和非旋转存储的混合禁用它。默认情况下禁用。

    -   [`innodb_idle_flush_pct`](innodb-parameters.html#sysvar_innodb_idle_flush_pct)

        允许在空闲期间限制页面刷新，这有助于延长非旋转存储设备的使用寿命。在 MySQL 8.0.18 中引入。

    -   [`innodb_io_capacity`](innodb-parameters.html#sysvar_innodb_io_capacity)

        对于低端的非旋转存储设备，默认设置 200 通常就足够了。对于更高端的总线连接设备，请考虑更高的设置，例如 1000。

    -   [`innodb_io_capacity_max`](innodb-parameters.html#sysvar_innodb_io_capacity_max)

        默认值 2000 适用于使用非循环存储的工作负载。对于高端、总线连接的非旋转存储设备，请考虑更高的设置，例如 2500。

    -   [`innodb_log_compressed_pa​​ges`](innodb-parameters.html#sysvar_innodb_log_compressed_pages)

        如果重做日志位于非循环存储上，请考虑禁用此选项以减少日志记录。看[禁用压缩页面的日志记录](optimizing-innodb-diskio.html#innodb-disable-log-compressed-pages).

    -   [`innodb_log_file_size`](innodb-parameters.html#sysvar_innodb_log_file_size)

        如果重做日志位于非循环存储上，请配置此选项以最大化缓存和写入组合。

    -   [`innodb_page_size`](innodb-parameters.html#sysvar_innodb_page_size)

        考虑使用与磁盘内部扇区大小相匹配的页面大小。早期的 SSD 设备通常具有 4KB 的扇区大小。一些较新的设备具有 16KB 的扇区大小。默认`InnoDB`页面大小为 16KB。使页面大小接近存储设备块大小可以最大限度地减少重写到磁盘的未更改数据量。

    -   [`binlog_row_image`](replication-options-binary-log.html#sysvar_binlog_row_image)

        如果二进制日志在非循环存储上并且所有表都有主键，请考虑将此选项设置为`最小的`以减少日志记录。

        确保为您的操作系统启用了TRIM支持。默认情况下，它通常处于启用状态。

-   增加I/O容量以避免积压

    如果吞吐量因以下原因而周期性下降：`InnoDB` [检查站](glossary.html#glos_checkpoint)操作，考虑增加价值[`innodb_io_容量`](innodb-parameters.html#sysvar_innodb_io_capacity)配置选项。值越高，导致频率越高[法拉盛](glossary.html#glos_flush)，避免可能导致吞吐量下降的积压工作。

-   如果冲洗没有落后，则降低I/O容量

    如果系统没有落后于`InnoDB` [法拉盛](glossary.html#glos_flush)操作，考虑降低[`innodb_io_容量`](innodb-parameters.html#sysvar_innodb_io_capacity)配置选项。通常，您会将此选项的值保持在尽可能低的水平，但不要太低，以致于如前一项所述，它会导致吞吐量周期性下降。在可以降低选项值的典型场景中，您可能会在[`显示引擎INNODB状态`](show-engine.html):

    -   历史记录列表长度较低，低于几千。

    -   插入缓冲区合并到插入的行附近。

    -   在缓冲池中修改的页面始终低于[`innodb_max_dirty_pages_pct`](innodb-parameters.html#sysvar_innodb_max_dirty_pages_pct)缓冲池的一部分。（在服务器未进行大容量插入时进行测量；在大容量插入期间，修改页面百分比显著上升是正常的。）

    -   `日志序列号-最后一个检查点`小于7/8或理想情况下小于总尺寸的6/8`InnoDB` [日志文件](glossary.html#glos_log_file).

-   在Fusion io设备上存储系统表空间文件

    通过将包含双写存储区域的文件存储在支持原子写入的Fusion io设备上，可以利用与双写缓冲区相关的I/O优化。（在MySQL 8.0.20之前，doublewrite缓冲区存储位于系统表空间数据文件中。从MySQL 8.0.20开始，存储区域位于doublewrite文件中。请参阅。）[第15.6.4节，“双写缓冲区”](innodb-doublewrite-buffer.html)。当双写存储区文件放置在支持原子写入的Fusion io设备上时，双写缓冲区将自动禁用，Fusion io原子写入将用于所有数据文件。此功能仅在Fusion io硬件上受支持，并且仅在Linux上对Fusion io NVMFS启用。为了充分利用这一功能[`innodb_flush_方法`](innodb-parameters.html#sysvar_innodb_flush_method)设置`O_DIRECT`推荐使用。

    笔记

    因为doublewrite buffer设置是全局的，所以对于不在Fusion io硬件上的数据文件，doublewrite buffer也被禁用。

-   [](<>)禁用压缩页面的日志记录

    当使用`InnoDB`桌子[压缩](glossary.html#glos_compression)功能，图像重新压缩[页](glossary.html#glos_page)写信给[重做日志文件](glossary.html#glos_redo_log)当对压缩数据进行更改时。这种行为是由[`innodb_日志_压缩页面`](innodb-parameters.html#sysvar_innodb_log_compressed_pages)，默认情况下启用该选项，以防止在不同版本的`兹利布`在恢复过程中使用压缩算法。如果你确定`兹利布`版本不可更改，请禁用[`innodb_日志_压缩页面`](innodb-parameters.html#sysvar_innodb_log_compressed_pages)减少修改压缩数据的工作负载的重做日志生成。
