在 Compute Engine 上配置 MySQL


Compute Engine 提供一系列不同的实例类型和存储选项,可用于从 MySQL 数据库读取和写入数据。为确保您能够为数据库工作负载实现最佳性能和费用,我们建议您在新型基础架构即服务 (IaaS) 产品上运行。

以下配置建议考虑到 MySQL 工作负载通常用于读取密集型系统(例如联机事务处理 [OLTP] 或支持典型 Web 应用的数据库)。它们还考虑了常见的配置选项,例如使用 MySQL 8.0 或更高版本以及使用 InnoDB 存储引擎。对于对性能敏感的工作负载,您可能需要调整配置以适应。我们建议您将本指南作为部署的起点,然后使用实际工作负载进行测试,以验证您的配置是否符合您的需求。

选择您的虚拟机 (VM)

对于 MySQL 工作负载,我们建议使用最新一代的 C 和 N 机器系列,因为它们包含适用于大多数实际 MySQL 配置的形状。如需简要了解这些机器系列,请参阅以下 Google Cloud 博文。这些机器系列使用 Titanium,并基于新一代 Intel、AMD 和 Axion 处理器

专注于效果

对于对性能敏感的工作负载(例如业务关键型 MySQL 数据库),我们建议您使用最新的 C4C4A 实例(如果您所在的区域提供)。如果您无法访问这些实例,C3C3D 实例也能提供类似的性能。

这些实例可为计算密集型操作提供最低且最稳定的延迟时间,并针对注重性能的工作负载提供了以下实用功能:

  • 通过提前通知控制主机维护事件
  • 控制单核 Turbo 提升功能,以实现更一致的性能
  • Tier_1 网络,可提高网络带宽

如果您使用的是 C4A、C3 或 C3D 实例,还可以使用本地固态硬盘 (Local SSD) 来满足特定的性能要求。

优化费用

对于主要优先事项是优化成本的工作负载(例如流量较低到中等的 MySQL 数据库,或在测试或开发环境中使用的 MySQL 数据库),我们建议您使用最新的 N4 实例。这些实例使用 Compute Engine 的下一代动态资源管理功能来优化总费用,同时保持稳定的性能,但不提供 C4、C4A、C3 和 C3D 提供的强大保证。如需了解详情,请参阅新一代动态资源管理

配置虚拟机的大小

对于您使用的任何虚拟机,请务必根据您期望的 MySQL 性能水平选择合适的虚拟机大小。

如果您的目标是实现每秒高写入交易量 (TPS) 性能,则主要要考虑的是块存储。如需了解详情,请参阅本页面后面的配置区块存储

如果您希望实现每秒读取查询次数 (QPS) 高的性能,我们强烈建议您使用 MySQL 基于 RAM 的缓冲池来缓存热数据并减少磁盘访问次数。如需最大限度地发挥这些优势,请按以下步骤操作:

  • 选择虚拟机大小,确保工作集(即数据库一次处理的数据总量)能放入缓冲区池。
  • 调整缓冲区大小,以使用虚拟机上的大部分 RAM。

为了尽可能降低按此方式调整虚拟机大小的费用,我们建议您使用 RAM 与虚拟 CPU (vCPU) 比率较高的虚拟机,以免为您未使用的 vCPU 付费。

为了实现适合大多数 MySQL 工作负载的理想平衡,请确定工作负载的工作集,然后选择 RAM 中适合该工作集的最小 highmem 实例规格。highmem 实例规格为每个 vCPU 分配了约 8 GB 的 RAM。这样,您就有足够的内存来缓存大型工作集,同时保留足够的 CPU 来处理高查询负载。

对于工作负载较大但查询率较低的工作负载,如果使用 N4 实例,您可以通过将自定义机器类型扩展内存搭配使用,进一步提高 RAM 与 vCPU 的比率,从而进一步优化总费用。

配置虚拟机的网络带宽

对于大多数 MySQL 用例,您可以坚持使用实例的默认网络带宽限制。如果这符合您的需求,则无需升级到 Tier_1 网络。

配置分块存储

Google Cloud Hyperdisk 是唯一适用于近期 Compute Engine 虚拟机系列的持久块存储产品。我们认为,Hyperdisk Balanced 最适合绝大多数 MySQL 工作负载。如需详细了解 Hyperdisk,请参阅 Hyperdisk 文档

Google Cloud Hyperdisk

Hyperdisk Balanced 提供以下功能:

  • 低成本的固态硬盘 (SSD) 延迟时间
  • 适用于需要高性能的应用的高性能配置
  • 高于 99.999% 的持久性,可防范业界普遍存在的硬件故障和静默数据损坏风险
  • 使用 Google 管理的加密密钥或客户管理的加密密钥对所有 Hyperdisk 静态数据进行加密

选择您的效果级别

借助 Hyperdisk Balanced,您可以独立于磁盘存储空间大小来选择性能级别,从而优化数据库性能,同时仅需支付工作负载所需的输入/输出 (I/O) 资源费用。如果 MySQL 数据库的缓冲区大于其工作集,那么在稳态操作期间,它可以从缓冲区中处理几乎所有读取查询,而无需访问磁盘。

如需为 Hyperdisk 卷选择性能级别,请考虑您的 MySQL 写入工作负载,并重点考虑以下事项:

  • 访问 InnoDB 重做日志
  • InnoDB 数据文件和索引的后续更新

在稳态操作之外,数据库维护事件也可能会导致磁盘性能出现更大的波动。发生此问题的频率往往会随数据库的写入工作负载而扩缩,因此在使用重做日志进行崩溃后恢复或通过读取上次备份以来的所有数据库更改来复制自己的备份系统等情况下,更有可能发生此问题。

调整磁盘大小

您可以通过以下三种常见策略来确定磁盘性能限制的大小:

  1. 使用默认配置。每块磁盘的每秒输入/输出 (IOPS) 至少为 3,000,吞吐量至少为 140 MiBps。这对于基本 MySQL 工作负载和操作系统 (OS) 启动卷来说已经足够了。如果您的用例超出了此范围,您可以按需修改预配的 I/O 性能,而无需停止工作负载。
  2. 衡量您现有的使用情况。如果您的数据库已在其他环境中运行,请以一分钟或更短的时间粒度记录其磁盘 IOPS 和吞吐量。收集一到两周的数据后,您的样本集将包含一些负载和正常维护事件波动,然后从该数据集中选择一个高百分位数值,并添加一个小缓冲区,以考虑自然增长或意外使用情况。
  3. 估算您的需求,然后稍后进行修改。如果您没有现有的数据源,可能需要先估算性能需求,然后在部署后进一步进行调整。我们建议您最初预配的值高于您认为所需的值,以免工作负载遇到性能瓶颈,然后最终降低预配的性能以适应工作负载。

提高磁盘性能

您可以将每个平衡 Hyperdisk 磁盘的性能提高到最高 160,000 IOPS 和 2,400 MBps 的吞吐量。虚拟机的大小有助于确定 Hyperdisk 的最大性能限制,因此,如果您希望获得非常高的 Hyperdisk 性能,则可能需要增加虚拟机的内核数量。如果您的最苛刻工作负载需要的磁盘性能超出了单个 Hyperdisk Balanced 磁盘所能提供的性能,您可以使用以下方法之一将多个 Hyperdisk Balanced 磁盘条状排列在一起:

  • 升级到 Hyperdisk Extreme
  • 使用其他软件独立磁盘冗余阵列 (RAID) 机制,例如 mdadm

在扩缩 MySQL 数据库时,您可以动态增加磁盘的容量和性能,而不会造成停机。这有助于执行无法放入 RAM 并溢出到磁盘的大型复杂联接的在线分析处理 (OLAP) 式工作负载的性能。在极少数情况下,需要极低存储延迟时间且可以容忍数据丢失的 MySQL 工作负载可以将其完整数据集存储在本地 SSD 上。您还可以使用以下混合解决方案来缩短读取延迟时间并限制耐久性降低:

  • 在 Hyperdisk 和本地 SSD 之间镜像数据集。
  • 使用卷管理器将本地 SSD 配置为底层 Hyperdisk 上存储的数据的缓存。

利用其他 Hyperdisk 功能

Hyperdisk 还提供以下功能,可增强或简化本地高可用性和灾难恢复工作流:

如需详细了解如何使用 MySQL for Compute Engine 配置这些功能,请参阅本页下文中的高可用性部分。

本地 SSD

某些 Compute Engine 机器系列允许您使用本地 SSD 而非 Hyperdisk。这些不是持久性存储空间,但 MySQL 工作负载通常会使用它们来存储临时表空间

如需了解如何使用本地 SSD 伸缩 MySQL 数据库,请参阅本页下文中的动态调整磁盘大小

其他 Compute Engine 功能

您可以使用以下 Compute Engine 功能来帮助优化 MySQL 部署。

Cloud Monitoring

如需监控虚拟机的性能和基础架构服务用量,请使用Google Cloud 控制台。在虚拟机实例页面的可观测性标签页中,您可以监控与性能相关的指标,例如实例的 CPU 和内存利用率、网络带宽和预配性能。同样,在磁盘页面的可观测性标签页中,您可以监控磁盘卷的吞吐量和 IOPS。

如需自定义您看到的性能指标,请使用 Cloud Monitoring 构建查询。您可以选择要查看基础架构服务的具体性能指标。对于 MySQL 专用指标,Compute Engine 提供了 MySQL 工作负载插件

配置操作系统的最佳实践

  • 使用适当的文件系统。Google 专注于针对 Linux 的 ext4 和 XFS 文件系统进行优化;不过,大多数文件系统都适合与 MySQL 搭配使用。
  • 在基本操作系统配置中关闭透明大内存页 (THP)。如需了解关闭 THP 的步骤,请参阅 THP 文档
  • 如果您使用的是 Linux,请使用 relatimelazytime 标志进行文件系统挂载配置。这可减少在读取、修改文件或更改文件元数据时更新文件的 atimemtimectime 值所产生的性能开销。

配置 MySQL 的最佳实践

我们建议您为 MySQL 使用以下配置设置。

  • 使用较新版本的 MySQL。Google 会重点针对 MySQL 8.0 及更高版本进行优化。
  • 增大缓冲区池的大小。MySQL 使用缓冲池在 RAM 中缓存数据,从而减少磁盘访问次数,从而提高读取性能。默认情况下,MySQL 的缓冲区大小为 128 MiB,对于大多数实际用例而言,这个大小太小。我们建议您将 innodb_buffer_pool_size 的大小增加到大于应用在数据库中访问的工作集的大小。这通常包括以下步骤:

    1. 衡量或估算 MySQL 实例的运行副本上的工作集大小。
    2. 选择虚拟机 (VM) 大小和配置,确保 RAM 足够满足该工作集的要求。
    3. 配置虚拟机上的缓冲区池大小,使其占用大部分可用 RAM。
  • 开启双写缓冲区。MySQL 有一个双写缓冲区,可帮助防范已损坏的写入。如果在写入过程中发生硬件故障或电源故障,则覆盖磁盘上多个块的写入可能只会部分提交,这种故障模式就是已损坏的写入。如需获享此保护,请开启 innodb_doublewrite

  • innodb_flush_log_at_trx_commit 的值设置为 1这样可以确保写入事务在提交时在磁盘上持久化。

  • 为降低性能开销,请为 innodb_flush_method 指定值。 对于 MySQL 8.0.14 及更高版本,请将 innodb_flush_method 的值设置为 O_DIRECT_NO_FSYNC,这是最佳值,但仅适用于这些版本。对于 8.0.14 之前的 MySQL 版本,请将 innodb_flush_method 的值设置为 O_DIRECT

  • 在高可用性复制场景中,将主数据库实例的 sync_binlog 值设置为 1MySQL 使用二进制日志将主数据库中的更改传达给次要数据库,这样可以确保二进制日志在事务提交时提交,并且数据库之间的复制延迟时间和目标恢复点 (RPO) 尽可能低。

  • 在 C 系列机器系列上使用 MySQL 时,请开启 innodb_numa_interleave 这样可以确保 MySQL 的缓冲区池可以利用非一致内存访问 (NUMA) 政策。

何时关闭双写缓冲区

MySQL 的双写入缓冲区可防止出现写入损坏,但对于 MySQL 写入事务,其性能开销最高可达 25%,这可能会影响事务延迟时间。Google Cloud Hyperdisk 还提供撕裂写入保护,因此,如果您使用 MySQL 直接写入在 Hyperdisk 上运行的 ext4 文件系统,则可以放心地关闭双写缓冲区。

不过,为了让 Hyperdisk 的已损坏写入保护功能发挥作用,您必须在数据库和磁盘之间配置文件系统和其他中间软件层,以避免在磁盘层上引入已损坏写入。以下列表提供了可能会在 Hyperdisk 层上引入已撕裂写入的配置示例:

  • 在容器(例如 Google Kubernetes Engine 或自托管 Kubernetes)中运行 MySQL 实例。
  • 在 XFS 文件系统上存储 MySQL 文件,而 XFS 文件系统在大多数 Linux 内核配置中不支持足够大的块大小。
  • 将 MySQL 文件存储在会导致磁盘条带化的冗余独立磁盘阵列 (RAID) 配置上,例如适用于 Linux 的 mdadm,或适用于 Windows 的 Storage SpacesStorage Spaces Direct
  • 将 MySQL 文件存储在卷管理器之上,例如适用于 Linux 的逻辑卷管理器 (LVM),或适用于 Windows 的存储空间和存储空间直接。
  • 将 MySQL 文件存储在 Hyperdisk 上,并将本地固态硬盘 (SSD) 配置为缓存,例如在 Linux 中使用 lvmcachedm-cachebcache,或在 Windows 中使用存储空间。

  • 使用嵌套虚拟化在虚拟机内运行 MySQL 实例。

虽然您可以设置上述配置,使其不会引入已撕裂的写入,但我们不建议您在使用这些配置时关闭双写缓冲区,因为验证给定配置是否安全很困难。

(可选)关闭双写缓冲区

如需关闭双写缓冲区,请完成以下步骤:

  1. 在 ext4 文件系统中,您必须启用 bigalloc 功能,并将文件系统的集群大小配置为 16KiB,或 16KiB 的更大次方倍数。这样可确保 MySQL 的写入不会在发送到 Hyperdisk 之前被文件系统拆分为单独的 I/O。如果未提高此限制或使用小于 16 KiB 的任何值,则无法防范已损坏的写入。例如,如果集群大小为 16KiB,则需要在创建文件系统时进行配置:

    mkfs.ext4 -O bigalloc -C 16384 /dev/<device-name>
    
  2. 停用 innodb_doublewrite,并将 innodb_flush_method 设置为 O_DIRECTO_DIRECT_NO_FSYNC(具体取决于您使用的 MySQL 版本,如上所述)。

配置高可用性 (HA) 和备份解决方案

我们强烈建议您为所有关键 MySQL 工作负载配置高可用性 (HA) 和备份解决方案,以保护它们。对于高可用性和备份,以下因素最重要:

HA 解决方案通常以接近零的 RTO 和 RPO 为目标,但只能防范基础架构故障。备份解决方案的目标 RTO 和 RPO 较长,但可覆盖更多故障场景,例如:

  • 意外删除数据
  • 勒索软件攻击
  • 自然灾害

配置高可用性 (HA)

HA 功能使用存储和计算冗余来确保您的 MySQL 数据库在主机故障或停机时减少停机时间,让客户端应用即使在实例或可用区不可用时也能访问其数据。

MySQL 支持以下模式的复制:

  • 异步模式。在异步模式下,主副本会在写入事务在本地提交后立即确认,因此,如果主副本发生中断,则在故障切换期间可能会丢失少量最近写入的数据,因为 RPO 接近于零,但实际上并非零。
  • 半同步模式。在半同步模式下,主服务器会等待确认事务,直到可配置数量的副本确认已收到事务。这样一来,在非预期故障切换期间不会丢失数据的可能性就会大大增加,因为 RPO 实际上为零。

对于这两种模式,RTO 取决于健康检查执行以下操作的速度:

  1. 确定失败的实例。
  2. 触发故障切换。
  3. 使用域名系统 (DNS) 或其他数据库服务器标识方法,通知客户端故障切换实例现在是主实例。

无论采用哪种复制模式,您都必须有一个要复制到的故障切换实例。您可以在以下任一位置找到该实例:

  • 与主实例位于同一可用区
  • 主可用区所在区域内的其他可用区
  • 位于与主实例不同的区域

为了确保即使在可用区服务中断期间也能保持高可用性,我们建议采用以下配置:

  • 将主实例和故障切换实例放置在不同的可用区中,无论它们是否位于同一区域内。
  • 使用异步复制。这是因为,如果您使用的是半同步复制,将主实例和故障切换实例放置在不同的可用区可能会导致写入事务提交延迟时间过长。
  • 如果您需要 RPO 为 0,请使用 Hyperdisk Balanced 高可用性,以便在同一区域中的两个可用区之间同步复制磁盘。如需了解详情,请参阅 Google 关于使用 Hyperdisk 高可用性提供高可用性服务的指南。配置 Hyperdisk Balanced 高可用性时,我们建议您与有状态的代管式实例组集成,以诊断实例运行状况问题并自动执行恢复操作。

配置备份和数据弹性方案

备份和数据弹性计划有助于防止在意外数据删除、勒索软件攻击和自然灾害等故障期间丢失数据。您还可以将其用作冷存储空间,以满足合规性和审核要求。对于 MySQL,您可以选择多种备份方法,其中一些方法在数据库级别运行,另一些方法在存储卷级别运行。选择方法时,您应主要考虑 RTO 和 RPO 要求。

在数据库级别进行备份

对于数据库级备份,请考虑使用 MySQL 提供的以下选项:

如需详细了解 MySQL 的数据库级备份选项,请参阅 MySQL 文档中的备份和恢复

对于上述任一选项,您都必须有一个用于复制备份数据的辅助存储系统。我们建议您使用以下工具:

使用 Hyperdisk 在存储级别创建快照和克隆

对于存储级备份,我们建议您使用 Hyperdisk 产品来截取快照、克隆和以其他方式捕获 MySQL 数据库的某个时间点视图。此方法的 RPO 取决于您截取数据库快照的频率,而 RTO 取决于您使用的具体解决方案。

如果快速恢复对您来说很重要,并且您只需要在一个可用区内进行备份,我们建议您使用 Hyperdisk 的即时快照。即时快照会增量捕获特定时间点的数据,并可以通过磁盘克隆功能将数据快速恢复到新的 Hyperdisk 卷,从而实现几分钟的 RTO。当磁盘内容被覆盖、删除或损坏时,您可以使用快照恢复数据,并且快照会在与来源磁盘相同的可用区或区域的本地位置提供。如需了解详情,请参阅即时快照简介

对于灾难恢复场景(其中数据必须以比原始磁盘更高的冗余度存储,并且存储在单独的位置,以确保单次灾难不会影响数据的所有副本),我们建议您使用 Hyperdisk 的归档和标准磁盘快照。归档快照和标准磁盘快照会创建磁盘中某个时间点的数据副本,并以不可变格式以高冗余度存储该副本。当您为磁盘创建多个快照(例如使用快照时间表)时,Hyperdisk 只会存储增量更改。如果您可以容忍较高的 RTO,则归档快照和标准磁盘快照非常适合,因为从快照存储空间将数据复制回虚拟机存储空间可能意味着数据需要更长时间才能恢复。如需了解详情,请参阅创建归档和标准磁盘快照

HyperDisk 的即时快照以及其归档快照和标准快照在单个磁盘中都具有崩溃一致性。这意味着,当您从快照恢复时,MySQL 数据库必须运行正常的 InnoDB 恢复步骤,才能使其日志和数据文件恢复到一致状态。这可能会延长 RTO,具体取决于 InnoDB 重做日志的配置。以下模式可能会进一步增加创建一致数据库快照的难度:

  • 您的 MySQL 数据库文件分布在多个卷中。
  • 您使用的是 Linux 软件 RAID 实用程序,例如 mdadm
  • 您已将 MySQL 的配置存储位置分隔到不同磁盘上的文件系统中。

如需创建在快照恢复后无需恢复的快照,请完成以下步骤:

  1. 暂时锁定对 MySQL 数据库的写入权限。
  2. 使用 LOCK INSTANCE FOR BACKUPFLUSH TABLES WITH READ LOCK 命令将所有进行中的缓冲区刷新到磁盘。
  3. 启动快照操作。
  4. 对于多磁盘场景,在 MySQL 级别刷新后,请在服务器上执行 syncfsfreeze 命令,将所有进行中的写入刷新到磁盘,并在文件系统级别暂停新传入的写入。

捕获数据库的初始快照后,您无需继续锁定磁盘,因为 Hyperdisk 会快速捕获时间点视图,然后可以异步处理任何后续的存储空间复制步骤。如果您需要执行这些步骤来确保快照一致性,并且希望消除对主数据库的写入影响,还可以对数据库副本(而非主数据库)运行备份。

后续步骤