本页介绍了如何使用反向复制为 MySQL 设置回退。回退是指制定应急计划,以便在遇到 Spanner 相关问题时还原到源 MySQL 数据库。
在遇到意外问题并需要以尽可能少地中断服务的方式回退到原始 MySQL 数据库时,反向复制非常有用。借助反向复制,您可以将写入 Spanner 的数据复制到源 MySQL 数据库,从而实现回退。这可确保两个数据库最终保持一致。
反向复制流程涉及以下步骤(这些步骤由 Spanner_to_SourceDb Dataflow 模板执行):
使用 Spanner 变更数据流从 Spanner 读取更改。
确保过滤模式为
forward_migration。使用 Spanner 迁移工具转换 Spanner 数据,使其与源数据库架构兼容。如需了解详情,请参阅自定义转换。
验证源数据库是否已包含指定主键的最新数据。
将数据写入源数据库。
使用 Spanner_to_SourceDb Dataflow 模板
Dataflow 模板可确保主键级别的一致性。该模板会在 Spanner 中创建元数据表(称为影子表),其中包含相应表的分片上最后一次写入事务的提交时间戳。
写入操作在主键的提交时间戳之前是一致的。
您可以将执行反向复制的 Dataflow 作业配置为以以下模式之一运行:
常规:这是默认模式。Dataflow 作业从 Spanner 变更数据流中读取事件,将其转换为与源数据库架构兼容的数据类型,然后将其应用于源数据库。作业会自动重试错误。在重试次数用尽后,它会将错误移至 Cloud Storage 存储桶中死信队列 (DLQ) 目录的
severe文件夹。该作业还会将所有永久性错误移至severe文件夹。RetryDLQ:在此模式下,Dataflow 作业会从 DLQ 的
severe文件夹中读取事件并重试这些事件。在修复所有永久性错误后运行此模式。此模式仅从 DLQ 读取数据,而不从 Spanner 变更数据流读取数据。如果从severe文件夹处理的记录被移至retry文件夹,作业会重试这些记录。
准备工作
确保源 MySQL 数据库与Google Cloud 项目(Dataflow 作业将在其中运行)之间存在网络连接。
在目标 MySQL 实例上将 Dataflow 工作器 IP 地址列入许可名单。
检查
source shards file中是否正确指定了 MySQL 凭证。检查 MySQL 实例是否已上线并正在运行。
验证 MySQL 用户是否对 MySQL 数据库拥有
INSERT、UPDATE和DELETE权限。验证您是否拥有运行 Dataflow Flex 模板所需的 IAM 权限。如需了解详情,请参阅构建和运行灵活模板。
验证端口
12345是否已打开,以便在 Dataflow 工作器虚拟机之间进行通信。
所需的角色
-
如需获得启动反向复制所需的权限,请让您的管理员向您授予实例的以下 IAM 角色:
-
Cloud Spanner Database User (
roles/spanner.databaseUser) -
Dataflow Developer (
roles/dataflow.developer)
-
Cloud Spanner Database User (
-
为确保 Compute Engine 服务账号具有启动反向复制所需的权限,请让您的管理员为 Compute Engine 服务账号授予实例的以下 IAM 角色:
-
Cloud Spanner Database User (
roles/spanner.databaseUser) -
Secret Manager Secret Accessor (
roles/secretmanager.secretAccessor) -
Secret Manager Viewer (
roles/secretmanager.viewer)
-
Cloud Spanner Database User (
运行反向复制
如需运行反向复制,请按以下步骤操作:
将会话文件上传到 Cloud Storage 存储桶。
为 DLQ 目录的
retry文件夹创建 Pub/Sub 通知。为此,您可以创建一个 Pub/Sub 主题,并为该主题创建一个 Pub/Sub 订阅。构建并暂存 Dataflow 模板。如需了解详情,请参阅构建模板。
使用以下 Google Cloud CLI 命令运行反向复制 Dataflow 模板:
gcloud dataflow flex-template run "spanner-to-sourcedb-job" \ --project "PROJECT" \ --region "REGION" \ --template-file-gcs-location "TEMPLATE_SPEC_GCSPATH" \ --parameters "changeStreamName=CHANGE_STREAM_NAME" \ --parameters "instanceId=INSTANCE_ID" \ --parameters "databaseId=DATABASE_ID" \ --parameters "spannerProjectId=SPANNER_PROJECT_ID" \ --parameters "metadataInstance=METADATA_INSTANCE" \ --parameters "metadataDatabase=METADATA_DATABASE" \ --parameters "sourceShardsFilePath=SOURCE_SHARDS_FILE_PATH" \ --parameters "startTimestamp=START_TIMESTAMP" \ --parameters "endTimestamp=END_TIMESTAMP" \ --parameters "shadowTablePrefix=SHADOW_TABLE_PREFIX" \ [--parameters "sessionFilePath=SESSION_FILE_PATH"] \ [--parameters "filtrationMode=FILTRATION_MODE"] \ [--parameters "shardingCustomJarPath=SHARDING_CUSTOM_JAR_PATH"] \ [--parameters "shardingCustomClassName=SHARDING_CUSTOM_CLASS_NAME"] \ [--parameters "shardingCustomParameters=SHARDING_CUSTOM_PARAMETERS"] \ [--parameters "sourceDbTimezoneOffset=SOURCE_DB_TIMEZONE_OFFSET"] \ [--parameters "dlqGcsPubSubSubscription=DLQ_GCS_PUB_SUB_SUBSCRIPTION"] \ [--parameters "skipDirectoryName=SKIP_DIRECTORY_NAME"] \ [--parameters "maxShardConnections=MAX_SHARD_CONNECTIONS"] \ [--parameters "deadLetterQueueDirectory=DEAD_LETTER_QUEUE_DIRECTORY"] \ [--parameters "dlqMaxRetryCount=DLQ_MAX_RETRY_COUNT"] \ [--parameters "runMode=RUN_MODE"] \ [--parameters "dlqRetryMinutes=DLQ_RETRY_MINUTES"] \ [--parameters "sourceType=SOURCE_TYPE"] \ [--parameters "transformationJarPath=TRANSFORMATION_JAR_PATH"] \ [--parameters "transformationClassName=TRANSFORMATION_CLASS_NAME"] \ [--parameters "transformationCustomParameters=TRANSFORMATION_CUSTOM_PARAMETERS"] \ [--parameters "filterEventsDirectoryName=FILTER_EVENTS_DIRECTORY_NAME"]
以下列表介绍了必需变量:
project: Google Cloud 项目 ID。region: Google Cloud 区域。template-file-gcs-location:您暂存 Dataflow 模板的 Cloud Storage 文件路径。changeStreamName:作业从中读取数据的 Spanner 变更数据流的名称。instanceId:Spanner 实例 ID。databaseId:Spanner 数据库 ID。spannerProjectId:Spanner 实例所在的项目 ID。metadataInstance:存储元数据的实例,连接器使用该元数据来控制变更数据流 API 数据的使用。metadataDatabase:存储连接器用于控制变更数据流 API 数据使用情况的元数据的数据库。sourceShardsFilePath:包含源分片连接配置文件信息的 Cloud Storage 文件的路径。
以下列表介绍了可选变量:
startTimestamp:开始读取变更的时间戳。 默认值为空。endTimestamp:读取更改的时间戳上限。如果您未提供时间戳,该进程将无限期地读取更改。默认值为空。shadowTablePrefix:用于命名影子表的前缀。默认值为shadow_。sessionFilePath:Cloud Storage 中会话文件的路径,其中包含 Spanner 迁移工具的映射信息。filtrationMode:用于确定如何根据条件过滤记录的模式。支持的模式为none或forward_migration。shardingCustomJarPath:Cloud Storage 中包含用于提取分片 ID 的逻辑的自定义 JAR 文件的位置(路径)。 默认值为空。shardingCustomClassName:具有自定义分片 ID 实现的完全限定类名。如果指定了shardingCustomJarPath,则此字段为必填字段。默认值为空。shardingCustomParameters:一个字符串,包含要传递给自定义分片类的任何自定义参数。默认值为空。sourceDbTimezoneOffset:源数据库相对于世界协调时间 (UTC) 的时区偏移量。示例:+10:00。默认值:+00:00。dlqGcsPubSubSubscription:在regular模式下运行时,Cloud Storage 通知政策中用于 DLQ 重试目录的 Pub/Sub 订阅。以projects/<PROJECT_ID>/subscriptions/<SUBSCRIPTION_ID>格式指定名称。设置此参数后,系统会忽略deadLetterQueueDirectory和dlqRetryMinutes。skipDirectoryName:系统在反向复制期间跳过的记录的写入目录。默认值:skip。maxShardConnections:每个分片允许的最大连接数。 默认值:10000。deadLetterQueueDirectory:用于存储 DLQ 输出的路径。默认值为 Dataflow 作业的临时位置下的目录。dlqMaxRetryCount:系统通过 DLQ 重试临时错误的次数上限。默认值:500。runMode:运行模式类型。选项为regular或retryDLQ。使用retryDLQ仅重试严重 DLQ 记录。默认值:regular。dlqRetryMinutes:DLQ 重试之间的分钟数。默认值:10。sourceType:要反向复制到的源数据库的类型。默认值:mysql。transformationJarPath:Cloud Storage 中自定义 JAR 文件的位置(路径),其中包含用于处理反向复制中的记录的自定义转换逻辑。默认值为空。transformationClassName:包含自定义转换逻辑的完全限定类名称。如果指定了transformationJarPath,则此字段为必填字段。默认值为空。transformationCustomParameters:一个字符串,包含要传递给自定义转换类的任何自定义参数。默认值为空。filterEventsDirectoryName:系统在反向复制期间跳过的记录的写入目录。默认值:skip。