本文說明如何使用反向複製功能,為 MySQL 設定備用。如果 Spanner 發生問題,您可透過回溯機制還原至來源 MySQL 資料庫。
如果遇到非預期的問題,需要復原至原始 MySQL 資料庫,同時盡可能減少服務中斷,反向複製功能就非常實用。反向複製功能可讓您在來源 MySQL 資料庫上複製寫入 Spanner 的資料,以便復原。
反向複製流程包含下列步驟,由 Spanner_to_SourceDb Dataflow 範本執行:
使用 Spanner 變更串流讀取 Spanner 中的變更。
使用
forward_migration篩選模式篩選記錄。使用 Spanner 遷移工具轉換 Spanner 資料,使其與來源資料庫結構定義相容。詳情請參閱「自訂轉換」。
請確認來源 MySQL 資料庫是否已包含指定主鍵的最新資料。如果已有較新的資料,管道會略過變更事件,以免覆寫較新的資料。
將資料寫入來源資料庫。
使用 Spanner_to_SourceDb Dataflow 範本
Dataflow 範本有助於確保主鍵層級的一致性。範本會在 Spanner 中建立中繼資料表 (稱為「影子資料表」),其中包含該特定資料表 shard 上最後一次寫入交易的修訂版本時間戳記。
寫入作業會與主鍵的修訂版本時間戳記保持一致。
反向複製作業會以持續串流的 Dataflow 工作形式執行。這項工作會從 Spanner 變更串流讀取異動事件,轉換為與來源資料庫結構定義相容的資料類型,然後寫入 MySQL 資料庫。如果事件發生暫時性錯誤,工作會透過 Cloud Storage 中的 retry/ 無效信件佇列 (DLQ) 目錄自動重試。如果事件發生永久性錯誤 (或超過重試次數),工作會將事件傳送至 severe/ DLQ 目錄,以供手動解決。如要進一步瞭解如何解決及重新播放失敗的記錄,請參閱「監控及解決反向複製錯誤」。
事前準備
確認來源 MySQL 資料庫與Google Cloud 專案之間的網路連線,Dataflow 工作會在該專案中執行。
將 Dataflow worker IP 位址加入來源 MySQL 執行個體的許可清單。
確認
source shards file中正確指定 MySQL 憑證。確認 MySQL 執行個體已連上網路並正在執行。
確認 MySQL 使用者對 MySQL 資料庫具有
INSERT、UPDATE和DELETE權限。確認您具備執行 Dataflow Flex 範本所需的 IAM 權限。詳情請參閱「建構及執行 Flex 範本」。
確認通訊埠
12345已開啟,可供 Dataflow worker VM 進行通訊。
必要的角色
-
如要取得啟動反向複製所需的權限,請要求管理員在執行個體中授予您下列 IAM 角色:
- Cloud Spanner 資料庫使用者 (
roles/spanner.databaseUser) - Dataflow 開發人員 (
roles/dataflow.developer)
- Cloud Spanner 資料庫使用者 (
-
為確保 Compute Engine 服務帳戶具備啟動反向複製作業所需的權限,請要求管理員將下列 IAM 角色授予執行個體上的 Compute Engine 服務帳戶:
- Cloud Spanner 資料庫使用者 (
roles/spanner.databaseUser) - Secret Manager 密鑰存取者 (
roles/secretmanager.secretAccessor) - Secret Manager 檢視者 (
roles/secretmanager.viewer)
- Cloud Spanner 資料庫使用者 (
執行反向複製作業
如要執行反向複製,請按照下列步驟操作:
將工作階段檔案上傳至 Cloud Storage bucket。
為 DLQ 目錄的
retry資料夾建立 Pub/Sub 通知。方法是建立 Pub/Sub 主題,以及該主題的 Pub/Sub 訂閱項目。建構並暫存 Dataflow 範本。詳情請參閱「建構範本」。
如要啟動反向複製串流管道,請執行下列
gcloud dataflow flex-template run指令: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" \ # All flags after this point are optional [--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:您要執行 Dataflow 工作的 Google Cloud 區域。TEMPLATE_SPEC_GCSPATH:暫存 Dataflow 範本檔案的 Cloud Storage 路徑。CHANGE_STREAM_NAME:作業讀取資料的 Spanner 變更串流名稱。INSTANCE_ID:Spanner 執行個體 ID。DATABASE_ID:Spanner 資料庫 ID。SPANNER_PROJECT_ID:Spanner 執行個體所在的專案 ID。METADATA_INSTANCE:Spanner 執行個體,用於儲存連接器控制變更串流 API 資料用量時所需的中繼資料。METADATA_DATABASE:Spanner 資料庫,用於儲存連接器控制變更串流 API 資料消耗量時使用的中繼資料。SOURCE_SHARDS_FILE_PATH:包含來源分片連線設定檔資訊的 Cloud Storage 路徑。
下表列出選用變數:
START_TIMESTAMP:開始讀取變更的時間戳記。預設為空白。END_TIMESTAMP:讀取變更的時間戳記。如未指定,程序會無限期讀取變更。預設為空白。SHADOW_TABLE_PREFIX:命名影子資料表的前置字串。預設值:shadow_。SESSION_FILE_PATH:Cloud Storage 中工作階段檔案的路徑,內含 Spanner 遷移工具的對應資訊。FILTRATION_MODE:根據條件篩選記錄的方式。支援的模式為none和forward_migration。SHARDING_CUSTOM_JAR_PATH:自訂 JAR 檔案在 Cloud Storage 中的位置 (路徑),該檔案包含擷取 shard ID 的邏輯。預設為空白。SHARDING_CUSTOM_CLASS_NAME:具有自訂分片 ID 實作項目的完整類別名稱。如果指定SHARDING_CUSTOM_JAR_PATH,則必須提供這項參數。預設為空白。SHARDING_CUSTOM_PARAMETERS:包含要傳遞至自訂資料分割類別的任何自訂參數的字串。預設為空白。SOURCE_DB_TIMEZONE_OFFSET:來源資料庫與世界標準時間的時區偏移量。例如,+10:00。預設值:+00:00。DLQ_GCS_PUB_SUB_SUBSCRIPTION:在regular模式下執行時,用於 DLQ 重試目錄的 Cloud Storage 通知政策中的 Pub/Sub 訂閱項目。請按照projects/<PROJECT_ID>/subscriptions/<SUBSCRIPTION_ID>格式指定名稱。設定這個參數時,系統會忽略deadLetterQueueDirectory和dlqRetryMinutes。SKIP_DIRECTORY_NAME:系統在反向複製期間略過記錄時,會將記錄寫入這個目錄。預設:skip。MAX_SHARD_CONNECTIONS:每個 shard 允許的連線數量上限。預設:10000。DEAD_LETTER_QUEUE_DIRECTORY:用於儲存 DLQ 輸出的路徑。預設值是 Dataflow 工作暫時位置下的目錄。DLQ_MAX_RETRY_COUNT:系統透過 DLQ 重試暫時性錯誤的次數上限。預設值:500。RUN_MODE:執行模式類型。支援的選項為regular、retryDLQ和retryAllDLQ。使用retryDLQ,在作用中的管道旁重試severe/目錄中的錯誤記錄,或在一般管道停止時,使用retryAllDLQ處理retry/和severe/目錄。預設值:regular。DLQ_RETRY_MINUTES:DLQ 重試間隔時間 (以分鐘為單位)。預設:10。SOURCE_TYPE:要反向複製到的來源資料庫類型。預設值:mysql。TRANSFORMATION_JAR_PATH:自訂 JAR 檔案在 Cloud Storage 中的位置 (路徑),該檔案包含用於處理反向複製記錄的自訂轉換邏輯。預設為空白。TRANSFORMATION_CLASS_NAME:具有自訂轉換邏輯的完整類別名稱。如果指定TRANSFORMATION_JAR_PATH,則必須提供這項參數。預設為空白。TRANSFORMATION_CUSTOM_PARAMETERS:字串,內含要傳遞至自訂轉換類別的任何自訂參數。預設為空白。FILTER_EVENTS_DIRECTORY_NAME:Cloud Storage 中的目錄,系統會將自訂反向轉換邏輯篩除的記錄寫入此處。預設值:filteredEvents。
監控及解決反向複製錯誤
從 Spanner 執行反向複製作業回到 MySQL 時,如果串流 Dataflow 工作無法將變更事件寫入 MySQL 主要資料庫,系統會將失敗歸類為下列其中一種類別,並將記錄寫入 Cloud Storage 值區中的死信佇列目錄:
- 可重試錯誤:暫時性失敗,例如 MySQL 資料庫鎖定爭用或網路連線逾時。Dataflow 會將這些事件寫入
retry/死信佇列目錄,並在同一管道中自動重試,直到成功或超過dlqMaxRetryCount為止。 - 嚴重錯誤:無法透過自動重試解決的永久性錯誤,例如資料類型轉換錯誤、語法錯誤,或自訂轉換 JAR 中的例外狀況。Dataflow 會將這些事件寫入
severe/無效信件佇列目錄 (例如gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/),並遞增自訂使用者計數器severe_error_count。
由於嚴重錯誤無法透過自動重試解決,Dataflow 會從有效的複製串流中移除這些失敗的事件,並將其儲存在 severe/ 目錄中。如果不處理,復原的 MySQL 資料庫就會缺少這些記錄。在反向複製期間,請定期監控 severe_error_count 計數器和 severe/ 目錄,以便在啟動回溯前解決並重新播放失敗的變更事件。
Dataflow 自訂計數器 severe_error_count 是累計指標,會記錄串流工作啟動以來發生的嚴重錯誤總數。使用 DLQ 重試工作重播及解決失敗記錄時,原始串流管道上的這個計數器不會遞減。因此,Cloud Storage 嚴重 DLQ 目錄 (gs://MIGRATION_BUCKET/ENV/SERVICE/reverse/DB_SCHEMA/severe/) 是判斷是否存在未處理錯誤的權威資訊來源。
重播失敗的記錄
如果嚴重 DLQ 目錄中出現失敗記錄,請檢查 Cloud Storage 中的 JSON 錯誤檔案,找出根本原因並解決潛在問題。
如要將修正後的 DLQ 記錄重播至 MySQL,請使用下列其中一種執行模式啟動新的 Dataflow 工作:
retryDLQ模式:與現有的串流管道一起以批次工作形式執行此模式,處理severe/目錄中的錯誤檔案,不會中斷即時反向複製作業。解決嚴重錯誤的根本原因後,請執行這個模式。retryAllDLQ模式:如果一般串流管道已停止,請使用這個模式處理retry/和severe/目錄。請勿在管道執行期間同時執行retryAllDLQ,否則會導致檔案爭用和處理衝突。
如要使用 gcloud CLI 啟動反向複製 DLQ 重試工作,請執行下列指令:
gcloud dataflow flex-template run "spanner-to-sourcedb-retry-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 "deadLetterQueueDirectory=DLQ_DIRECTORY" \
--parameters "runMode=retryDLQ"
更改下列內容:
PROJECT: Google Cloud 專案 ID。REGION:您要執行 Dataflow 工作的 Google Cloud 區域。TEMPLATE_SPEC_GCSPATH:暫存 Dataflow 範本檔案的 Cloud Storage 路徑。CHANGE_STREAM_NAME:工作讀取的 Spanner 變更串流名稱。INSTANCE_ID:Spanner 執行個體 ID。DATABASE_ID:Spanner 資料庫 ID。SPANNER_PROJECT_ID:Spanner 執行個體所在的專案 ID。METADATA_INSTANCE:Spanner 執行個體,用於儲存連接器控制變更串流 API 資料用量時所需的中繼資料。METADATA_DATABASE:Spanner 資料庫,用於儲存連接器控制變更串流 API 資料消耗量時使用的中繼資料。SOURCE_SHARDS_FILE_PATH:Cloud Storage 路徑,其中包含來源 shard 的連線設定檔資訊。DLQ_DIRECTORY:Cloud Storage 路徑,指向含有嚴重錯誤檔案的無效信件佇列目錄,以便重試。