从 MySQL 迁移到 Cloud SQL

本文介绍如何规划和执行将未分区的 MySQL 5.7 数据库迁移到 Cloud SQL(这是 Google Cloud Platform (GCP) 上的一项全托管式数据库服务)的过程。本文假定您有一个 MySQL 数据库,并且非常熟悉 MySQL 和 GCP 概念。

本文中介绍的概念也适用于其他 MySQL 版本和 MariaDB(MySQL 的热门开源分支)。但是,对于 MySQL 5.7 以外的版本,您可能需要对相关过程进行细微修改。许多第三方工具和 Cloud SQL 合作伙伴产品可供您用来规划数据库迁移。本文只讨论原生 MySQL 和 GCP 功能,而不讨论其他任何工具或合作伙伴产品。

配套教程可引导您完成本文中所述的其中一个迁移过程。

概览

如需将 MySQL 数据库迁移到另一个环境,您需要迁移以下两个元素:

  • 数据库中的数据。这是数据库的“存储层”
  • 处理对存储层进行的一致性读写操作的管理系统。这是“管理层”

挑战在于,为使数据库正常运行,您需要不断同步这些元素。即使是小型数据库,也可能每秒收到数千个请求。如果存储层和管理层之间出现事务延迟或网络问题,这将对数据库、从属应用和用户满意度产生负面影响。

迁移方法

MySQL 具有两项可帮助您向 Cloud SQL 执行迁移的特性。这些特性是以下两种 MySQL 数据库迁移策略的基础:导出/导入迁移策略和外部副本升级迁移策略。

导出/导入迁移

在导出/导入策略中,您需要先使用 MySQL mysqldump 命令导出源数据库的存储层中的所有数据,然后再将这些数据直接导入新数据库的管理层。此策略通常需要数据库在整个迁移过程中处于停机状态,以确保所有数据保持同步。

外部副本升级迁移

在外部副本升级迁移策略中,您需要创建一个外部数据库副本,并将现有数据同步到该副本。此策略可以最大限度地缩短现有数据库的停机时间。

如果您有一个副本数据库,那么两个数据库将具有不同的角色,这对角色可以称为“主数据库/副本数据库”、“主数据库/从数据库”或“主数据库/跟随数据库”。本文采用“主数据库/副本数据库”这对术语

完成数据同步后,将副本升级为主数据库,以便在迁移管理层时将对数据库正常运行时间的影响降至最低。

在 Cloud SQL 中,完成外部副本升级的一种简单方法是使用自动化迁移工作流。这个过程可自动执行此类迁移所需的大多数步骤。

准备 MySQL 数据库以进行迁移

在执行迁移步骤之前,您需要确保数据库已针对任一迁移策略做好准备。MySQL 安装了一些默认配置,可以根据应用的要求进行调整和自定义。在开始迁移之前,请务必按照本部分中的说明配置 MySQL。这不但有助于降低迁移失败的风险,还有助于限制停机时间。

执行逻辑备份

无论使用哪种迁移方法,您都将需要对 MySQL 数据库进行更改。为了保护数据库中的数据,您应在执行任何迁移操作之前,使用 MySQL mysqldump 命令创建一个数据导出文件并将其作为备份保留。两种迁移方法都可从此备份着手。

mysqldump 命令用于截取数据库中所有数据的快照。此过程所需的时间可以从不到一秒到数小时不等,具体取决于数据库的大小。如果您在截取快照后更改了任何数据,则这些更改不会被捕获到最终快照中。如果您采用的是外部副本升级迁移过程,那么这就不会成为问题。但对于导出/导入迁移过程,这可能会导致数据不一致和数据丢失。

请将完整备份存储在一个安全位置。您可以选择使用 Cloud Storage、本地对象存储系统和异地备份。

对数据库性能指标进行基准测试

在开始任何迁移之前,您应全面收集现有应用和数据库的性能基准。这样,您就能够了解预期行为和当前性能指标。

确保您收集的基准数据能够反映您应用和数据库的使用场景。以后使用基准数据比较所迁移数据库的性能时,您需要确保可以在新旧数据库部署之间进行有意义的比较。

确定您的连接方案

网络连接要求因迁移策略而异。为帮助您确定可使用的方法,您需要了解的最重要的一点是,您的数据库是否可使用公共 IPv4 地址进行访问。

使用 Cloud SQL 自动化迁移工作流执行外部副本升级迁移时,您的现有数据库必须能够使用 IPv4 地址公开访问。Cloud SQL 中的目标数据库在整个升级或迁移过程中始终需要持久的网络连接。这种连接可能会持续较长时间,具体取决于您的数据库的大小。

您还应考虑目标数据库的连接方案。Cloud SQL 可以使用专用 IP 地址,也可以配置为使用公共 IP 连接

确定 root 密码

在迁移期间,您将运行许多特权 MySQL 命令和任务。因此,您必须能够访问 MySQL root 用户或具有 SUPERGRANT 权限的帐号。如果您不知道其中一个特权帐号的用户名和密码,则需要咨询数据库管理员或按照 MySQL 密码重置过程操作。

执行测试迁移并创建 Runbook

在执行生产迁移之前,您应先执行测试迁移。这样,您就可以验证您的步骤,增强对所采用方法的信心,并预测迁移所需的时间。您可以利用从此过程中吸取的经验教训生成一份 Runbook,以用于支持您的迁移。将此 Runbook 作为工作文档有助于对您的迁移进行协调和问题排查,以及确保其顺利执行。

本文可作为创建数据库迁移 Runbook 的入门指南。

准备应用以进行数据库迁移

最后一步准备工作是为迁移准备您的应用。所有应用到数据库的连接方法都不在本文的讨论范围内。但是,您有必要了解 IP 地址和域名系统 (DNS) 连接对您的应用有何影响。

常见的数据库访问方法是使用公共或内部 DNS;使用 DNS 时,您可以在不更新应用代码的情况下更改目标数据库的底层 IP 地址。如果您的应用依赖 DNS 记录来建立数据库连接,您通常需要为迁移降低这些 DNS 记录的 DNS 生存时间 (TTL) 值。

DNS TTL 值以秒为单位来度量,用于表示存储在客户端或主机上的 DNS 记录的有效性。此时间也称为 DNS 缓存期。默认 DNS TTL 值因 DNS 提供商而异。例如,Cloud DNS 将默认 TTL 设置为 5 分钟(300 秒)。由于数据库 DNS 条目很少会发生变化,因此您的 DNS 管理员可能已设置更高的 DNS TTL 值。

当您迁移数据库时,如果 DNS TTL 设置得较高,那么在客户端具有缓存 DNS 值的情况下,数据库的停机时间可能会延长。通过降低 TTL 值,您可以强制客户端更频繁地检查更新记录。此操作有助于将数据库停机时间保持在最低限度。

如果预计数据库的 DNS 记录会发生更改,您应该将此数值设置为可能限度的最低可配置值。如果您的 DNS 提供商是基于 SaaS,此操作可能会导致费用增加。进行这项更改之前,请务必先咨询您的提供商或管理员。

导出/导入迁移

导出/导入迁移策略依赖 MySQL mysqldump 命令从源环境数据库中导出逻辑快照。之后,您需要将此快照导入到目标环境数据库中。

这种迁移方法非常简单,但数据库会在迁移过程中发生停机。由于大型数据库会不断发生事务,因此管理员通常需执行以下操作:

  1. 停用源数据库写入新数据的能力。
  2. 从源数据库创建快照。
  3. 将快照导入到目标数据库。
  4. 更新应用配置,使其指向新数据库。
  5. 验证新数据库的性能。

下图展示了这一系列操作:

迁移顺序:从本地 MySQL 数据库,到导出至 Cloud Storage 的文件,再到 Cloud SQL 上运行的 MySQL

这一系列操作可确保从您停止对源数据库的写操作到开始对新数据库的写操作这段时间内,数据不会发生任何更改。此过程可能会导致应用的停机时间延长,具体取决于您的数据的大小。这对于许多业务和应用而言通常是不可接受的。

使用导出/导入迁移策略时,您的数据库不需要与 Cloud SQL 的外部连接。但是,您需要能够将 mysqldump 文件导出到一个可供 Cloud SQL 访问的位置。根据 mysqldump 文件的大小,此数据导入/导出过程可能会花费很长时间,并且可能需要复杂的文件复制和验证技术,以确保正确复制所有数据行和所有事务信息。

此外,您组织的数据分类规则也可能会限制您将 mysqldump 文件存储在其他位置。选择任何数据存储方法之前,请务必先查阅这些规则。

导出/导入迁移分步说明

以下部分详细介绍了这一系列操作所涉及的各个步骤。

停用写入功能

管理员配置数据库以禁止写操作。这也称为锁定或冻结数据库。此操作完成后,发送到数据库的任何写事务都会失败。但是,针对数据库或任何副本的读取事务仍会正常执行。在进行后续步骤之前,您应先运行几个测试查询来验证上述行为。

请务必了解锁定数据库可能会给哪些应用带来影响。您可能需要通知依赖数据库的用户、客户、管理员和其他部门,以防发生更大的系统故障。

导出数据

锁定数据库后,在旧数据库中执行 mysqldump 命令以导出所有数据。导出过程完成后,您必须将此文件移动到一个可供新数据库访问的位置。

请确保将备份文件发送到一个不包含生产数据库的物理硬盘。这种分离可以降低磁盘 I/O 争用,并且可以加快备份速度。将写入负载从主硬盘中移除会降低对生产数据库操作的影响。这种分离还可以降低包含生产数据库的磁盘出现空间不足的可能性。

此外,压缩 mysqldump 命令的输出也有助于减少备份所需的总写入次数。压缩可能需要更多的 CPU 资源,因此请务必检查这可能会如何影响数据库管理层的性能。

如需了解详情,请参阅导出数据以导入到 Cloud SQL 中

导入数据

新数据库必须从旧数据库中导入转储文件。导入过程将重新创建数据库表以及旧数据库中的所有行。在系统资源相同的情况下,导入所需的时间与导出所需的时间相当。如果您要在迁移过程中升级系统资源,则导入过程的执行速度可能要比导出过程快。

如需了解详情,请参阅将数据导入到 Cloud SQL 中

导入数据后,您应该查看通过测试源数据库而获得的性能基准测试信息。您随后可以对新数据库运行基于读取的生产查询,以确保新数据库满足您应用的性能需求。

更新应用

准备好开始使用新数据库后,您需要更新您的应用,使其支持新数据库。您可以通过以下几种方法完成此任务:

  • 如果您的应用在源代码中直接定义了数据库端点或 IP 地址,请更新该代码并将这项更新部署到所有需要访问数据库的应用。
  • 如果您的应用在访问数据库时指向 DNS 记录,请通过 DNS 提供商更新 DNS 记录以反映新的数据库端点地址。
  • 如果您的应用在访问数据库时指向负载平衡器,请将新的数据库端点注册到负载平衡器。

如果要切换您的应用以使用 Cloud SQL,您可能需要预热缓冲池。这有助于在数据库将数据存储到内存之前,最大限度地减少应用可能面临的查询延迟时间。您可以使用源生产数据库中的 MySQL 慢查询日志来创建一个脚本,以用于执行所有将填充新实例上的缓存的 SELECT 语句。建议您在开始启用写入功能之前执行此操作。

您可以借助许多第三方工具和合作伙伴产品来预热您的缓冲池。

启用写入功能

验证更新后的应用代码可与新数据库通信之后,您需要移除新数据库的只读锁。完成该步骤后,您可以通过应用验证数据库是否正常运行。您还应执行另一轮基准测试,以确保数据库性能仍满足应用的需求。

完成验证并确定两个数据库之间的所有数据均一致之后,您可以完成几项清理任务:

  • 通知用户停机时间已结束。
  • 更新状态页面并从应用中移除所有状态消息。
  • 将所有修改后的 DNS TTL 还原为其原始值。

优化导入时间的建议做法(适用于导出/导入迁移)

您可以通过多种方法优化 mysqldump 文件的导入速度,继而缩短服务器需要处于只读状态的总时间。

  • 优化您的架构。设计数据结构以避免外键。如果可能,请按主键顺序导出数据。
  • 优化您的资源。如果可能,请启动配有足够 RAM 的新数据库,以支持整个数据集。此外,将 SSD 作为数据库存储空间可以大大提高数据吞吐量。与机械磁盘相比,SSD 支持更高的每秒输入/输出操作数 (IOPS)。GCP SSD 也会随着磁盘大小的增加而提高 IOPS。这意味着,为了获得更高的 IOPS,超额预配更大磁盘空间的额外开支也许物有所值。
  • 优化监控。实施强大的监控解决方案以检测新旧数据库所存在的任何问题,这对于迁移而言非常有用。例如,您可以使用 StackdriverMySQL 插件。通过监控,您可以及早检测出问题,确定正常的数据库行为,并将新数据库与以前的数据库基准进行比较。

导出和导入大型数据库

mysqldump 进程可以快速处理小于 10 GB 的数据库。如果导入的数据库大于 10 GB,您可能需要采用高级策略,以最大限度减少数据库在最终切换期间发生的停机时间。

分段导出架构和数据

一种策略是分段导出数据库架构和数据,而不使用辅助键。这样,您就可以在迁移结束时使用 ALTER TABLE 语句添加辅助键。使用这种方法时,您可以先根据表的键关系将几组不同的表导出到不同的文件,然后从 Compute Engine 实例并行运行 MySQL 导入过程。如需导出要并行导入的数据,一种方法是手动修改导出文件本身。但是,此操作可能非常耗时且容易出错。

利用时间戳

如果您的任何表使用时间戳列,您可以使用 mysqldump 命令来指定 WHERE 子句。这样,您就可以通过多次导入操作将带有时间戳的数据加载到 Cloud SQL 中。

准备好进行最终迁移切换后,您可以使用此方法仅导出源数据库中自上次导出之后发生了更改的那些行。如果您的表不带时间戳,并且您能够熟练地在源数据库表中引入时间戳列,则可以为每个源表添加一个 MySQL 触发器,以便在某个行发生变化时设置时间戳。

使用这种方法时,需要考虑的一个问题是跟踪已删除的行。时间戳列只能跟踪通过 INSERTUPDATE 语句更改的行,而已删除的行会从表中移除。因此,只有在将应用和数据库构建为使用软删除机制的情况下,才可以使用时间戳来查找已在初始迁移后删除的行。在这种方法中,您无需发出 DELETE 语句,只需将 is_deleted 列设置为 true 以指示某行已被删除。或者,您也可以创建一个表来跟踪每个实际表的已删除行,并创建一个匹配的 on_delete 触发器来将已删除的行插入删除跟踪表中。在迁移过程的最后阶段,您可以创建必要的 DELETE 语句以从 Cloud SQL 实例中移除这些行。

验证导出文件

每当手动修改导出文件或导出不同表时,您都应该验证数据是否已准确导出。

比较导出文件

验证导出数据的一种方法是实现一个空闲测试数据库。如需创建空闲测试数据库,您可以将最新的生产备份恢复到一个新的独立数据库实例,然后将您的 mysqldump 文件恢复到此新的空闲测试数据库。接下来,您可以测试多阶段的 mysqldump 过程,然后将其并行恢复到另一个空闲测试数据库。这样一来,您应该会获得数据库的两个相同副本。随后,您便可验证数据,方法是对两个空闲测试数据库运行 mysqldump 命令,并使用 diff 命令或文件比较工具来比较所有三个数据库。

下图演示了这一系列操作,并显示了在此过程中创建的工件。

用于验证导出文件的操作序列和工件

外部副本升级

另一种迁移 MySQL 数据库的方法是使用外部副本升级。在此策略中,您需要创建一个副本数据库并将现有数据库设置为主数据库。您需要等到两个数据库同步后,才能将 MySQL 副本数据库升级为主数据库。此过程可最大程度地减少因数据库迁移而造成的数据库停机时间。

前提条件

如需使用外部副本升级迁移方法,您还需要满足另外两个前提条件,即创建复制用户和启用 GTID 复制功能。

建立复制用户

MySQL 的某些版本(包括 5.7 版,本文中的示例采用此版本)会将用于执行复制的任何用户帐号的用户名和密码以明文形式存储在主数据库的日志中。如果您使用 root 用户帐号执行复制,则 root 密码将存储在纯文本日志中。因此,使用 root 用户身份进行复制会构成安全风险。

为了防止数据库的其他方面受到破坏,您应该创建一个完全独立的帐号来执行复制。这个新帐号应该只拥有执行复制过程所需的权限。此外,该帐号应该只能从主数据库的 IP 地址进行复制。

配置 GTID

您的源数据库必须启用 GTID 复制功能,才能执行外部副本升级迁移。如果您尚未在源数据库中配置复制功能,则 GTID 复制可能不会启用。

全局事务标识符 (GTID) 是与主数据库服务器上提交的每项事务关联的唯一标识符。这些标识符用于在副本数据库和主数据库之间构建复制过程。

默认情况下,Cloud SQL for MySQL 的新实例会使用 GTID 复制。您无法停用此功能,因此不允许使用某些 SQL 语句和操作。如需了解详情,请参阅 Cloud SQL 与标准 MySQL 功能之间的差异 MySQL 对 GTID 复制的限制

外部副本升级迁移概览

与导出/导入迁移相比,外部副本升级迁移要简单得多。如果您已完成前文描述的所有前提条件,则可以借助 Cloud SQL 来自动执行此过程。虽然自动化迁移工作流仍然需要执行导出/导入过程,但它消除了自动化过程中的一些手动步骤。

自动化迁移工作流支持以下场景:

  • 从本地迁移到 Cloud SQL。
  • 从其他云服务商迁移到 Cloud SQL。
  • 从一个 GCP 项目迁移到另一个 GCP 项目。

在自动化迁移工作流中,您需要执行以下操作:

  1. 提供有关您数据源的详细信息。
  2. 创建一个 Cloud SQL 读取副本。
  3. 将该读取副本与您的数据源同步。
  4. 将 Cloud SQL 读取副本升级为主实例。

提供有关数据源的详细信息

使用 Cloud SQL 运行自动化迁移工作流时,您需要提供数据源的参考名称。该名称用于引用迁移中的数据,无需与数据源的实际名称完全一致。

您还需提供源数据库的公共 IP 地址和端口。您需要确保您的 Cloud SQL 数据库使用 IPv4 地址直接连接到源数据库,还需要确保将保护源数据库的所有防火墙或安全设备配置为允许来自新的 Cloud SQL 数据库 IP 地址的连接。

此外,您还必须为自动化迁移工作流提供 MySQL 复制用户凭据和要迁移的 MySQL 版本。在下一步中,您将需要使用这些信息来向服务器进行身份验证以及支持安全转移。您还可以根据需要配置 SSL/TLS 选项。

创建 Cloud SQL 读取副本

运行自动化迁移工作流时,您需要设置用于在 GCP 中创建新 Cloud SQL 实例的选项。此操作涉及以下几个步骤:

  • 设置数据库实例 ID。
  • 选择 GCP 区域和地区。
  • 选择实例类型。
  • 选择磁盘存储类型。
  • 选择总存储容量。我们建议启用存储空间自动扩容功能。 此选项使您的数据库能够根据需要进行扩展,并降低数据库用尽磁盘空间的风险。

最后,您需要提供指向存储在 Cloud Storage 中的快照的链接。请确保将最新的导出文件存储在与 Cloud SQL 实例位于同一项目的 Cloud Storage 存储分区中。

将读取副本与数据源同步

在开始迁移过程之后,新的 Cloud SQL 虚拟机将启动并开始从数据源进行复制。同步完成后,您可以比较数据库中的数据以确认复制是否已完成。您也可以开始进行基准测试,以针对您应用的要求和先前测得的源数据库基准性能来测试 Cloud SQL 数据库的性能。

将读取副本升级为主实例

复制数据后,请将旧数据库置于只读模式。这样可以阻止对该数据库的任何写入,并确保数据在升级过程中不会发生更改。然后,请更新应用代码或 DNS 条目以支持 Cloud SQL 中的新端点(如前所述)。

如果源数据库处于只读模式,并且您的应用已使用新的 Cloud SQL 端点地址进行更新,您可以转到 Cloud SQL 中的新数据库实例并将副本升级为主服务器。此升级过程会自动重新启用对新升级的 Cloud SQL 主数据库的写入。

将副本升级为主服务器后,无论数据库大小如何,您的数据库都可能会面临几分钟的停机。这是为了让 Cloud SQL 执行升级该数据库所涉及的所有任务和配置工作。

升级完成后,您的主数据库会在 Cloud SQL 中运行,并且迁移过程也已完成。此时,您最好针对应用要求和源数据库基准性能运行另一组性能测试。获得一组新的 Cloud SQL 性能基准测试值后,您可以规划其他数据库优化。

在迁移后进行优化

迁移完成后,无论采用哪种迁移方法,您都可以通过以下方式优化 Cloud SQL 数据库:

  • 合理调整虚拟机的容量。通过分析监控数据,您可以了解是否需要为数据库选择其他容量的虚拟机。使用更小型的实例有助于降低费用;使用配备更多资源的更大型虚拟机有助于您的数据库发挥更高的性能。
  • 添加其他索引。如果添加其他索引或其他优化能够为您的数据库带来好处,您可以在完成迁移后添加它们。
  • 开启其他事务性日志记录。请探索服务器日志记录级别,以深入了解启用二进制日志记录功能或其他增强型日志记录选项的好处。
  • 对于外部副本升级迁移方法,请重新启用二进制日志记录功能并利用自动备份(副本升级迁移完成后,二进制日志记录功能会关闭,继而导致 Cloud SQL 自动备份停用)。

后续步骤