数据库迁移:概念和原则(第 1 部分)

Last reviewed 2024-03-07 UTC

本文档面向需要将数据库从本地或其他云环境迁移到 Google Cloud 的云架构师,介绍了接近零停机时间数据库迁移的概念、原则、术语和架构。

本文档为两部分文章中的第 1 部分。第 2 部分讨论了如何设置和执行迁移过程(包括故障场景)。

数据库迁移是使用数据库迁移服务将数据从一个或多个源数据库迁移到一个或多个目标数据库的过程。迁移完成后,源数据库中的数据集会完全保留在目标数据库中,但可能会发生重组。然后,之前访问源数据库的客户端会切换到目标数据库,源数据库则会关闭。

下图展示了上述数据库迁移过程。

通过迁移服务从源数据库迁移到目标数据库的数据流。

本文档将从架构角度介绍数据库迁移:

  • 数据库迁移涉及的服务和技术。
  • 同构与异构数据库迁移之间的差异。
  • 迁移停机时间容忍度的权衡和选择。
  • 当迁移过程中发生意外错误时支持后备的设置架构。

本文档不会介绍如何设置具体的某种数据库迁移技术,而是介绍数据库迁移的基础知识、概念和原则。

架构

下图展示了一个通用数据库迁移架构。

访问源数据库和目标数据库的迁移服务的架构。

数据库迁移服务在 Google Cloud 中运行,并且可以访问源数据库和目标数据库。下面是两种变化形式:(a) 显示从本地数据中心或远程云中的源数据库迁移到 Spanner 等代管式数据库;(b) 显示迁移到 Compute Engine 上的数据库。

对于上述两种情况,虽然目标数据库在类型(代管式和非代管式)和设置方面有所不同,但数据库迁移架构和配置却是相同的。

术语

这些文档最重要的数据迁移术语定义如下:

源数据库:包含要迁移到一个或多个目标数据库的数据的数据库。

目标数据库:接收从一个或多个源数据库迁移过来的数据的数据库。

数据库迁移:将数据从源数据库迁移到目标数据库,最终在迁移完成后会关闭源数据库系统。可以迁移整个数据集,也可以迁移部分数据集。

同构迁移:从源数据库迁移到目标数据库,其中源数据库和目标数据库属于同一提供商的同一数据库管理系统。

异构迁移:从源数据库迁移到目标数据库,其中源数据库和目标数据库属于不同提供商的不同数据库管理系统。

数据库迁移系统:连接到源数据库和目标数据库并执行从源数据库到目标数据库的数据迁移的软件系统或服务。

数据迁移过程:由数据迁移系统执行,将数据从源数据库转移到目标数据库的已配置或实现的过程,在转移期间可能会转换数据。

数据库复制:将数据从源数据库持续转移到目标数据库,最终不会关闭源数据库。数据库复制(有时称为“数据库流式传输”)是一个持续的过程。

数据库迁移分类

数据库迁移具有不同类型,这些类型又属于不同类别。本部分将介绍定义这些类别的条件。

复制与迁移

在数据库迁移中,您将数据从源数据库移动到目标数据库。在数据完全迁移后,删除源数据库并将客户端访问重定向到目标数据库。有时,您可以保留源数据库,作为在目标数据库出现意外问题时的后备措施。但是,当目标数据库能够可靠运行后,您最终需要删除源数据库。

相比之下,使用数据库复制时,您可以将数据从源数据库持续转移到目标数据库,且不会删除源数据库。有时,数据库复制被称为数据库流式传输。虽然定义了开始时间,但通常未定义完成时间。复制可能会停止,也可能会变为迁移。

本文档仅讨论数据库迁移。

部分迁移与完全迁移

您可以将数据库迁移理解为一种完整且一致的数据转移。您可以将要转移的初始数据集定义为完整数据库或部分数据库(数据库中的部分数据),然后再加上之后在源数据库系统上提交的每项更改。

异构迁移与同构迁移

同构数据库迁移是指在采用同一数据库技术的源数据库和目标数据库之间进行迁移,例如,从 MySQL 数据库迁移到 MySQL 数据库,或从 Oracle® 数据库迁移到 Oracle 数据库。同构迁移还包括自托管数据库系统(例如 PostgreSQL)与其托管式版本(例如 Cloud SQL for PostgreSQL 或 AlloyDB for PostgreSQL)之间的迁移。

在同构数据库迁移中,源数据库和目标数据库的架构可能相同。如果架构不同,则必须在迁移期间转换源数据库中的数据。

异构数据库迁移是指在采用不同数据库技术的源数据库和目标数据库之间进行迁移,例如,从 Oracle 数据库迁移到 Spanner。异构数据库迁移可以发生在相同数据模型之间(例如,从关系型到关系型),也可以发生在不同数据模型之间(例如,从关系型到键值对)。

在不同数据库技术之间迁移不一定会涉及不同的数据模型。例如,Oracle、MySQL、PostgreSQL 和 Spanner 均支持关系型数据模型。但是,Oracle、MySQL 或 PostgreSQL 等多模型数据库支持不同的数据模型。在多模型数据库中以 JSON 文档形式存储的数据几乎或完全不需要转换即可迁移到 MongoDB,因为源数据库和目标数据库中的数据模型相同。

虽然同构迁移与异构迁移之间的区别基于数据库技术,但另一种分类却基于涉及的数据库模型。例如,如果都使用关系型数据模型,则从 Oracle 数据库到 Spanner 的迁移为同构迁移;如果将 Oracle 中以 JSON 对象的形式存储的数据迁移到 Spanner 中的关系模型,则该迁移为异构迁移。

根据数据模型对迁移进行分类比根据所涉及的数据库系统进行分类更加准确地体现了迁移数据复杂性和所需的工作。但由于业界常用的分类基于所涉及的数据库系统,因此本文剩余部分将重点讨论数据库系统。

迁移停机时间:零停机时间、最短停机时间和较长停机时间

在将数据集从源数据库成功迁移到目标数据库后,您可以将客户端访问切换到目标数据库并删除源数据库。

将客户端从源数据库切换到目标数据库涉及多个过程:

  • 要继续处理,客户端必须关闭与源数据库建立的现有连接,并与目标数据库建立新连接。理想情况下,关闭连接是安全的,这意味着您不必回滚正在进行的事务。
  • 关闭源数据库上的连接后,您必须将其余更改从源数据库迁移到目标数据库(称为“排空”),以确保捕获所有更改。
  • 您可能需要测试目标数据库,以确保这些数据库正常运行,并确保客户端正常运行且不超出其定义的服务等级目标 (SLO)。

在迁移中,客户端不可能实现真正的零停机时间;有时客户端会无法处理请求。但是,您可以通过以下多种方式最大限度地缩短客户端无法处理请求的时长(接近于零的停机时间):

  • 您可以在客户端进行切换之前,提早在目标数据库中以只读模式启动测试客户端。通过此方法,测试可与迁移同时进行。
  • 在切换期临近时,您可以将迁移中的数据量(即在源数据库和目标数据库之间迁移的数据量)尽可能配置为最小值。此步骤可减少排空时间,因为源数据库和目标数据库之间的差异更小。
  • 如果在目标数据库上运行的新客户端可以与在源数据库上运行的现有客户端同时启动,则可以缩短切换时间,因为新客户端可以在所有数据排空后立即运行。

虽然在切换过程中实现零停机时间是不现实的,但您可以通过尽可能在进行数据迁移的同时启动活动,最大限度地缩短停机时间。

在某些数据库迁移场景中,较长的停机时间是可以接受的。这一般取决于业务要求。在这些情况下,您可以简化您的方法。例如,在同构数据库迁移中,您可能不需要修改数据;导出和导入或备份和恢复是最佳方法。在异构迁移中,数据库迁移系统无需在迁移期间处理源数据库系统的更新。

但是,您需要确定可接受的停机时间是否足以进行数据库迁移和后续测试。如果无法确定此停机时间或该时间过长,您需要计划一项停机时间最短的迁移。

数据库迁移基数

在许多情况下,数据库迁移在单个源数据库和单个目标数据库之间进行。在这些情况下,基数为 1:1(直接映射)。也就是说,源数据库不作更改便迁移到目标数据库。

但是,直接映射并不是唯一的可能性。其他基数包括:

  • 合并 (n:1)。在合并方法中,您可以将数个源数据库中的数据迁移到数量更少的目标数据库(甚至是一个目标数据库)。您可以使用此方法来简化数据库管理或使用可扩缩的目标数据库。
  • 分布 (1:n)。在分布方法中,您可以将数据从一个源数据库迁移到多个目标数据库。例如,当您需要将包含区域数据的大型集中式数据库迁移到多个区域目标数据库时,可以使用此方法。
  • 重新分布 (n:m)。在重新分布方法中,您可以将数据从多个源数据库迁移到多个目标数据库。在使用分片大小不同的分片源数据库时,可以使用此方法。重新分布将分片数据均匀分布在表示分片的多个目标数据库上。

除了迁移数据之外,数据库迁移还提供了重新设计和实现数据库架构的机会。

迁移一致性

数据库迁移应该是一致的。在迁移环境中,一致性表示以下特性

  • 完整。指定要迁移的所有数据实际上都已迁移。指定数据可以是某个源数据库中的所有数据,也可以是部分数据。
  • 无重复。每份数据都会迁移且仅迁移一次。目标数据库中不会引入重复的数据。
  • 有序。源数据库中的数据更改按照更改在源数据库中出现的顺序应用于目标数据库。这一点对于确保数据一致性至关重要。

描述迁移一致性的另一种方法是迁移完成后,源数据库和目标数据库之间的数据状态对等。例如,在涉及直接映射关系型数据库的同构迁移中,源数据库和目标数据库中必须存在相同的表和行。

这种描述迁移一致性的替代方法非常重要,因为并非所有数据迁移都基于将源数据库中的事务按顺序应用到目标数据库。例如,您可以备份源数据库,并使用备份将源数据库内容恢复到目标数据库中(当可能出现较长停机时间时)。

主动-被动迁移与主动-主动迁移

一项重要区别是源数据库和目标数据库是否都可以修改查询处理。在主动-被动数据库迁移中,可以在迁移期间修改源数据库,而只能对目标数据库进行只读访问

主动-主动迁移支持客户端在迁移期间同时写入源数据库和目标数据库。在这种类型的迁移中,可能会发生冲突。例如,如果源数据库和目标数据库中的相同数据项被修改以致在语义上相互冲突,则您可能需要运行冲突解决规则来解决此冲突。

在主动-主动迁移中,您必须能够使用冲突解决规则来解决所有数据冲突。如果不能,则可能会遇到数据不一致的问题。

数据库迁移架构

数据库迁移架构描述了执行数据库迁移所需的各种组件。本部分介绍了一个通用部署架构,并将数据库迁移系统视为一个单独的组件。此外,本部分还讨论了数据库管理系统的功能,该系统支持数据迁移以及对许多使用场景来说都非常重要的非功能属性。

部署架构

数据库迁移可以在任何环境(例如本地或各种云)中的源数据库和目标数据库之间进行。每个源数据库和目标数据库可分别位于不同环境中;它们不一定都要位于同一环境。

下图展示了涉及多个环境的部署架构示例。

涉及云和本地数据中心的迁移架构。

DB1 和 DB2 是两个源数据库,DB3 和 Spanner 是目标数据库。此数据库迁移涉及两个云和两个本地数据中心。箭头表示调用关系:数据库迁移服务调用所有源数据库和目标数据库的接口。

此处未讨论的一种特殊情况是将数据从某个数据库迁移到相同数据库。此特殊情况将数据库迁移系统仅用于数据转换,而不是用于跨不同环境在不同系统之间迁移数据。

从根本上说,数据库迁移具有三种方法,本部分将分别进行讨论:

数据库迁移系统

数据库迁移系统是数据库迁移的核心。系统从源数据库执行实际数据提取,将数据传输到目标数据库,并在传输过程中选择性地修改数据。本部分大致介绍基本的数据库迁移系统功能。数据库迁移系统示例包括 Database Migration ServiceStriimDebeziumtcVisionCloud Data Fusion

数据迁移过程

数据库迁移系统的核心技术要素是数据迁移过程。数据迁移过程由开发者指定,定义了从中提取数据的源数据库、要将数据迁移到其中的目标数据库以及在迁移过程中应用于数据的任何数据修改逻辑

您可以指定一个或多个数据迁移过程,并根据迁移的需要按顺序或同时执行这些过程。例如,如果您迁移独立数据库,则相应数据迁移过程可以并行运行。

数据提取和插入

您可以通过两种方式发现数据库系统中是否发生更改(插入、更新、删除):数据库支持的基于事务日志的更改数据捕获 (CDC),以及使用数据库管理系统的查询接口对数据本身进行差分查询。

基于事务日志的 CDC

数据库支持的 CDC 基于与查询接口无关的数据库管理功能。一种方法基于事务日志(例如 MySQL 中的二进制日志)。事务日志包含按正确顺序对数据进行的更改。由于系统会持续读取事务日志,因此可以观察到所有更改。对于数据库迁移,此日志记录极其有用,因为 CDC 可确保每项更改都可见且随后按正确顺序迁移到目标数据库,不会发生丢失。

在数据库管理系统中,CDC 是捕获更改的首选方法。CDC 内置于数据库本身,对系统的负载影响最小。

差分查询

如果不存在支持观察所有更改是否采用正确顺序的数据库管理系统功能,您可以使用差分查询作为替代方法。在此方法中,数据库中的每个数据项都会获得一个包含时间戳或序列号的额外属性。每次更改数据项时,系统都会添加更改时间戳或增加序列号。轮询算法会读取自上次执行更改的时间以来或自更改上次使用的序列号之后的所有数据项。在轮询算法确定更改后,它会将当前时间或序列号记录到其内部状态,然后将更改传递给目标数据库。

虽然此方法对于插入和更新没有问题,但您仍需要谨慎设计删除,因为删除操作会从数据库中移除数据项。删除数据后,轮询器将无法检测到已发生的删除操作。您可以使用指示数据已删除的其他状态字段(逻辑删除标志)实现删除。或者,可以将已删除的数据项收集到一个或多个表中,轮询器会访问这些表以确定是否发生了删除操作。

如需了解差分查询的变体,请参阅更改数据捕获

差分查询是最不推荐的方法,因为它涉及架构和功能更改。查询数据库还会添加与执行客户端逻辑无关的查询负载。

适配器和代理

数据库迁移系统需要访问来源和数据库系统。适配器是封装访问功能的抽象。在最简单的情况下,适配器可以是 JDBC 驱动程序,用于将数据插入支持 JDBC 的目标数据库。在稍复杂的情况下,适配器在目标环境(有时称为“代理”)中运行,并访问日志文件等内置数据库接口。在更复杂的情况下,适配器或代理会与另一个软件系统连接,而该软件系统又会反过来访问数据库。例如,代理访问 Oracle GoldenGate,而后者又会反过来访问 Oracle 数据库。

访问源数据库的适配器或代理会实现 CDC 接口或差分查询接口,具体取决于数据库系统的设计。在这两种情况下,适配器或代理都会向数据库迁移系统提供更改,因此数据库迁移系统就不清楚是 CDC 还是差分查询捕获了这些更改。

数据修改

在某些使用场景中,数据会在未修改的情况下从源数据库迁移到目标数据库。这种直接迁移通常是同构迁移。

但是,许多使用场景需要在迁移过程中修改数据。当架构存在差异、数据值存在差异或有机会在数据转换期间清理数据时,通常需要修改数据。

以下部分讨论了数据迁移中可能需要的几种类型的修改 - 数据转换、数据丰富或关联、数据缩减或过滤。

数据转换

数据转换可转换源数据库中的部分或所有数据值。下面是一些示例:

  • 数据类型转换。有时,源数据库和目标数据库之间的数据类型并不对等。在这些情况下,数据类型转换可根据类型转换规则将源值强制转换为目标值。例如,源数据库中的时间戳类型可被转换为目标数据库中的字符串。
  • 数据结构转换。数据结构转换可修改同一数据库模型中或不同数据库模型之间的结构。例如,在关系型系统中,一个源表可被拆分为两个目标表,或者多个源表可通过联接反规范化为一个目标表。源数据库中的 1:n 关系可能被转换为 Spanner 中的父子关系。源文档数据库系统中的文档可被分解为目标系统中的一组关系行。
  • 数据值转换。数据值转换与数据类型转换彼此独立。数据值转换会更改值,但不会更改数据类型。例如,本地时区被转换为世界协调时间 (UTC)。或者,以字符串表示的短邮政编码(五位数字)被转换为长邮政编码(五位数字后跟短划线和四位数字,也称为 ZIP+4)。
数据丰富和关联

数据转换应用于现有数据,不会引用其他相关参考数据。而使用数据丰富功能,系统将查询其他数据以丰富源数据,然后再将其存储到目标数据库中

  • 数据关联。您可以关联源数据。例如,您可以合并两个源数据库的两个表中的数据。例如,在一个目标数据库中,您可以将客户与所有未结订单、已履行的订单和已取消的订单相关联,从而使用两个不同的源数据库生成了客户数据和订单数据。
  • 数据丰富。数据丰富功能会添加参考数据。例如,您可以通过添加与邮政编码对应的城市名称来丰富仅包含邮政编码的记录。包含邮政编码和相应城市名称的参考表是在此使用场景中访问的静态数据集。参考数据也可以是动态数据。例如,您可以使用所有已知客户的列表作为参考数据。
数据缩减和过滤

另一种类型的数据转换是在将源数据迁移到目标数据库之前对其进行缩减或过滤。

  • 数据缩减。数据缩减会移除数据项中的属性。例如,如果数据项中存在邮政编码,因为系统可以重新计算相应的城市名称或者不再需要该名称,则可能不需要该城市名称并且会将其删除。有时,由于历史记录的原因,系统会保留此信息,以记录用户输入的城市名称(即使城市名称随时间发生了变化)。
  • 数据过滤。数据过滤会完全移除数据项。例如,所有已取消的订单都可能会被移除并且不会被转移到目标数据库。
数据组合或重组

如果将数据从不同源数据库迁移到不同目标数据库,则可能需要在源数据库和目标数据库之间以不同方式组合数据。

假设客户和订单存储在两个不同的源数据库中。一个源数据库包含所有订单,另一个源数据库包含所有客户。迁移后,客户及其订单以 1:n 的关系存储在单个目标数据库架构中,但不是在单个目标数据库中,而是在多个目标数据库中,其中的每个数据库都包含一个数据分区。每个目标数据库表示一个区域,并包含位于该区域的所有客户及其订单。

目标数据库寻址

除非只有一个目标数据库,否则迁移的每个数据项都需要发送到正确的目标数据库。目标数据库寻址包括以下几种方法:

  • 基于架构的寻址。基于架构的寻址根据架构确定目标数据库。例如,客户集合的所有数据项或客户表的所有行都会被迁移到存储客户信息的同一目标数据库,即使此信息分布在多个源数据库中也是如此。
  • 基于内容的路由。基于内容的路由(例如,使用基于内容的路由器)根据数据值确定目标数据库。例如,位于拉丁美洲区域的所有客户都会被迁移到表示该区域的特定目标数据库。

您可以在数据库迁移中同时使用这两种类型的寻址。无论使用哪种寻址类型,目标数据库都必须具有正确的架构,以便存储数据项。

保留传输中的数据

数据库迁移系统或该系统运行的环境可能会在迁移过程中发生故障,传输中的数据可能会丢失。发生故障时,您需要重启数据库迁移系统,并确保存储在源数据库中的数据会一致且完整地迁移到目标数据库。

在恢复过程中,数据库迁移系统需要识别上次成功迁移的数据项,以确定从源数据库中的哪个位置开始进行提取。要在发生故障时进行恢复,系统需要保留迁移过程中的内部状态。

您可以通过以下几种方式保留状态:

  • 您可以在发生任何数据库修改之前在数据库迁移系统中存储所有提取的数据项,然后在数据项的修改版本成功存储到目标数据库之后移除这些数据项。此方法可确保数据库迁移系统可以准确地确定提取和存储的内容。
  • 您可以保留对传输中的数据项的引用列表。一种可能的情况是将每个数据项的主键或其他唯一标识符与状态属性一起存储。发生故障后,此状态将是以一致方式恢复系统的基础。
  • 您可以在发生故障后查询源数据库和目标数据库,以确定源数据库系统和目标数据库系统之间的差异。此差异决定要提取的下一个数据项。

其他保持状态的方法取决于特定的源数据库。例如,数据库迁移系统可以跟踪从源数据库提取了哪些事务日志条目,以及哪些事务日志条目插入到了目标数据库。如果发生故障,可从上次成功插入的条目重新开始迁移。

保留传输中的数据对于错误或故障之外的其他原因也很重要。例如,可能无法查询源数据库中的数据以确定其状态。例如,如果源数据库包含队列,则该队列中的消息可能已在某一时刻被移除。

需要保留传输中的数据的另一个使用场景是对数据进行大窗口处理。在数据修改过程中,数据项可以彼此独立完成转换。但是,有时数据修改取决于多个数据项(例如,对每天处理的数据项进行编号,且每天都从零开始)。

需要保留传输中的数据的最后一个使用场景是,当数据库系统无法再次访问源数据库时,在数据修改期间提供数据可重复性。例如,您可能需要使用不同修改规则重新执行数据修改,然后验证结果并将这些结果与初始数据修改进行比较。如果您需要跟踪由于数据修改错误而导致目标数据库中出现的任何不一致情况,则可能需要使用此方法。

完整性和一致性验证

您需要验证您的数据库迁移是否完整且一致。此检查可确保每个数据项仅迁移一次、源数据库和目标数据库中的数据集相同以及迁移已完成。

根据数据修改规则,系统可能会提取数据项,但不会将其插入目标数据库。因此,直接比较源数据库和目标数据库并不是验证完整性和一致性的可靠方法。但是,如果数据库迁移系统跟踪被滤除的项,则您可以将源数据库和目标数据库与滤除的项一起进行比较。

数据库管理系统的复制功能

在同构迁移中,一个特殊的使用场景是目标数据库是源数据库的副本。具体来说,源数据库和目标数据库中的架构相同,数据值相同,并且每个源数据库都是直接映射 (1:1) 到目标数据库。

在这种情况下,您可以使用大多数数据库管理系统附带的内置复制功能将一个数据库复制到另一个数据库。

数据复制有两种类型:逻辑复制和物理复制。

  • 逻辑复制:对于逻辑复制,数据库对象中的更改会根据其复制标识符(通常是主键)转移。逻辑复制的优点是它灵活、精细,并且可以对其进行自定义。在某些情况下,逻辑复制可让您在不同的数据库引擎版本之间复制更改。许多数据库引擎都支持逻辑复制过滤条件,您可以在其中定义要复制的数据集。主要缺点是逻辑复制可能会产生一些性能开销,并且此复制方法的延迟时间通常高于物理复制。

  • 物理复制:相比之下,物理复制在磁盘块级层运行,具有更好的性能和更短的复制延迟时间。对于大型数据集,物理复制可能更直接且更高效,尤其是在非关系型数据结构的情况下。但是,它不可自定义,并且很大程度上取决于数据库引擎版本。

示例包括 MySQL 复制PostgreSQL 复制(另请参阅 pglogical)或 Microsoft SQL Server 复制

但是,如果需要修改数据,或者您除了直接映射之外还有其他任何基数,则需要数据库迁移系统的功能来应对此类应用场景。

自定义数据库迁移功能

构建数据库迁移功能而不是使用数据库迁移系统或数据库管理系统的一些原因包括:

  • 您需要完全控制每一个细节。
  • 您想要重复使用数据库迁移功能。
  • 您希望降低费用或简化技术足迹。

构建迁移功能的要素包括:

  • 导出和导入:在同构数据库迁移中,如果停机时间并非影响因素,则您可以使用数据库导出和数据库导入来迁移数据。但是,导出和导入要求您在导出数据之前让源数据库处于静默状态以防止更新。否则,在导出中可能不会捕获到更改,并且目标数据库不会是源数据库的准确副本。
  • 备份和恢复:与导出和导入的情况一样,备份和恢复会导致停机,因为您需要让源数据库处于静默状态,以便备份包含所有数据和最新更改。停机时间会一直持续到目标数据库上成功完成恢复为止。
  • 差分查询:如果可以选择更改数据库架构,则您可以扩展该架构,以便在查询接口查询数据库更改。系统添加了额外的时间戳属性,用于指示上次更改的时间。您可以添加额外的删除标志,用于指示数据项是否已被删除(逻辑删除)。通过这两项更改,按固定间隔执行的轮询器可以查询自上次查询以来的所有更改。这些更改应用于目标数据库。如需了解其他方法,请参阅更改数据捕获

以上只是用于构建自定义数据库迁移的几个可能的选项。虽然自定义解决方案提供了最灵活和最大控制程度的实现,但它还需要持续维护以解决错误、可扩缩性限制以及在数据库迁移过程中可能出现的其他问题。

数据库迁移的其他注意事项

以下部分简要讨论了在数据库迁移场景中非常重要的非功能性方面。这些方面包括错误处理、可扩缩性、高可用性和灾难恢复。

错误处理

数据库迁移期间发生的故障不得导致数据丢失或对数据库更改的处理出现混乱。无论造成故障的原因(例如系统错误、网络中断、虚拟机崩溃或地区故障)是什么,都必须要保持数据完整性。

如果迁移系统从源数据库检索数据,但由于某些错误而未将该数据存储到目标数据库中,则会发生数据丢失。发生数据丢失时,目标数据库与源数据库不匹配,因此该数据库不一致且不完整。完整性和一致性验证功能将标记此状态(完整性和一致性验证)。

可扩缩性

在数据库迁移中,迁移时间是一项重要指标。在零停机时间的迁移(从最短停机时间意义上说)中,发生数据迁移时源数据库会继续进行更改。要在合理的时间范围内迁移,数据传输速率必须要比源数据库系统的更新速率快得多,尤其是在源数据库系统较大时。传输速率越高,数据库迁移就完成得越快。

当源数据库系统处于静默状态且未被修改时,迁移可能会更快,因为没有要整合的更改。在同构数据库中,迁移时间可能会非常快,因为您可以使用备份和恢复功能或导出和导入功能,并且文件转移会发生扩缩。

高可用性和灾难恢复

源数据库和目标数据库通常都配置为高可用性。主数据库具有相应的读取副本,发生故障时,该读取副本会提升为主数据库。

当某个区域发生故障时,源数据库或目标数据库会故障切换到另一个区域以便继续可用。如果在数据库迁移期间发生区域故障,迁移系统本身会受到影响,因为它访问的多个源数据库或目标数据库会变得无法访问。迁移系统必须重新连接到发生故障后运行的新提升的主数据库。重新连接数据库迁移系统后,该系统必须恢复迁移本身,以确保目标数据库中数据的完整性和一致性。迁移系统必须确定上次的一致传输,以确定要恢复的位置。

如果数据库迁移系统本身发生故障(例如,其运行的地区变得无法访问),则必须恢复该系统。一种恢复方法是冷重启。在此方法中,数据库迁移系统安装在正常运行的地区并重启。要解决的最大问题是,迁移系统必须能够确定故障前上一次的一致数据传输,并从该位置继续,以确保目标数据库中的数据完整且一致。

如果数据库迁移系统已启用高可用性,则可以进行故障切换并在之后继续进行处理。如果必须限定数据库迁移系统的停机时间,则您需要选择数据库并实现高可用性。

在恢复数据库迁移方面,灾难恢复与高可用性非常类似。数据库迁移系统必须重新连接到其他地区(故障切换地区)中的数据库,而不是重新连接到其他区域中新提升的主数据库。这同样适用于数据库迁移系统本身。如果数据库迁移系统运行的区域变得无法访问,则数据库迁移系统必须故障切换到其他区域并从上一次的一致数据传输继续。

隐患

一些隐患可能会导致目标数据库中的数据不一致。下面是一些需要避免的常见隐患:

  • 违反顺序。如果通过横向扩容来实现迁移系统的可扩缩性,则多个数据传输过程会同时(并行)运行。源数据库系统中的更改将按照提交的事务进行排序。如果从事务日志中获取更改,则必须在整个迁移过程中保留此顺序。由于底层进程之间的速度不同,并行数据传输会更改此顺序。请务必按照从源数据库接收数据的顺序将数据插入目标数据库。
  • 违反一致性。使用差分查询时,源数据库将具有其他数据属性,例如包含提交时间戳的属性。目标数据库不会有提交时间戳,因为提交时间戳仅用于在源数据库中建立变更管理机制。请务必确保插入到目标数据库的内容必须在时间戳上保持一致,这意味着具有相同时间戳的所有更改都必须位于同一插入、更新或更新插入事务中。否则,如果插入了一些更改,但未插入具有相同时间戳的另一些更改,则目标数据库可能会出现不一致状态(暂时)。如果未访问目标数据库以进行处理,则此暂时的不一致状态无关紧要。但是,如果目标数据库用于测试,则一致性至关重要。另一个方面是在源数据库中创建时间戳值,以及这些值与设置它们的事务的提交时间之间的关系。由于事务提交的依赖关系,具有较早时间戳的事务可能会在具有较晚时间戳的事务之后可见。如果在这两个事务之间执行差分查询,则该查询将看不到具有较早时间戳的事务,从而导致目标数据库不一致。
  • 数据缺失或重复。发生故障切换时,如果未在主数据库和故障切换副本之间复制某些数据,则需要谨慎恢复。例如,源数据库发生故障切换,但并非所有数据都被复制到故障切换副本。同时,数据已在发生故障前迁移到目标数据库。进行故障切换后,新提升的主数据库在对目标数据库的数据更改(称为“闪回”)方面相对落后。迁移系统需要识别此情况并从这种情况中恢复,以使目标数据库和源数据库恢复到一致状态。
  • 本地事务。要使源数据库和目标数据库接收相同的更改,一种常见方法是让客户端同时向源数据库和目标数据库进行写入,而不是使用数据迁移系统。这种方法存在一些隐患。其中一个隐患是,两个数据库写入是两个单独的事务;您可能会在第一个数据库写入完成之后且在第二个数据库写入完成之前遇到故障。这种情况会导致数据不一致,您必须从不一致中恢复过来。此外,一般来说,还存在几个未进行协调的客户端。这些客户端不知道源数据库事务提交顺序,因此无法对实现该事务顺序的目标数据库进行写入。客户端可能会更改此顺序,从而导致数据不一致。除非所有访问都通过协调的客户端进行,并且所有客户端都确保遵循目标事务顺序,否则此方法可能会导致目标数据库出现不一致状态。

总的来说,还有一些需要注意的其他隐患。要找出可能导致数据不一致的问题,最好的方法是进行完整的故障分析,遍历所有可能的故障场景。如果数据库迁移系统中实现了并发操作,则必须检查所有可能的数据迁移过程执行顺序,以确保保持数据一致性。如果实现了高可用性和/或灾难恢复,则必须检查所有可能的故障组合。

后续步骤