教學課程:透過 Azure CLI 使用 DMS 將 PostgreSQL 遷移至在線 適用於 PostgreSQL 的 Azure 資料庫

您可以使用 Azure 資料移轉服務,將資料庫從內部部署PostgreSQL實例移轉至 適用於 PostgreSQL 的 Azure 資料庫,停機時間最短。 換句話說,在應用程式停機時間最少的情況下,即可達成移轉。 在本教學課程中,您會使用 Azure 資料移轉服務 中的在線移轉活動,將 DVD Rental 範例資料庫從 PostgreSQL 9.6 的內部部署實例移轉至 適用於 PostgreSQL 的 Azure 資料庫。

在本教學課程中,您會了解如何:

  • 使用 pg_dump 公用程式移轉範例架構。
  • 建立 Azure 資料移轉服務的實例。
  • 使用 Azure 資料移轉服務 建立移轉專案。
  • 執行移轉。
  • 監視移轉。

注意

使用 Azure 資料移轉服務 來執行在線移轉需要根據 進階版 定價層建立實例。 我們會加密磁碟,以防止在移轉過程中竊取數據。

重要

為了獲得最佳移轉體驗,Microsoft 建議在與目標資料庫相同的 Azure 區域中建立 Azure 資料移轉服務 實例。 跨區域或地理位置行動數據可能會減緩移轉程式,並引入錯誤。

必要條件

若要完成本教學課程,您需要:

  • 下載並安裝 PostgreSQL社群版本 9.4、9.5、9.6或10。 來源 PostgreSQL Server 版本必須是 9.4、9.5、9.6、10、11、12 或 13。 如需詳細資訊,請參閱支援的 PostgreSQL 資料庫版本。

    另請注意,目標 適用於 PostgreSQL 的 Azure 資料庫 版本必須等於或更新於內部部署PostgreSQL版本。 例如,PostgreSQL 9.6 只能遷移至 適用於 PostgreSQL 的 Azure 資料庫 9.6、10 或 11,但無法移轉至 適用於 PostgreSQL 的 Azure 資料庫 9.5。

  • 在 適用於 PostgreSQL 的 Azure 資料庫建立 適用於 PostgreSQL 的 Azure 資料庫 - 超大規模資料庫 (Citus) 伺服器中建立實例。

  • 使用 Azure Resource Manager 部署模型建立適用於 Azure 資料庫移轉服務的 Microsoft Azure 虛擬網路,此模型會使用 ExpressRouteVPN 提供內部部署來源伺服器的站對站連線。 如需建立虛擬網路的詳細資訊,請參閱虛擬網路文件,特別是快速入門文章,裡面會提供逐步操作詳細資料。

    注意

    在虛擬網路設定期間,如果您使用 ExpressRoute 搭配網路對等互連至 Microsoft,請將下列服務 端點 新增至將布建服務的子網:

    • 目標資料庫端點 (例如,SQL 端點、Azure Cosmos DB 端點等)
    • 儲存體端點
    • 服務匯流排端點

    此為必要設定,因為 Azure 資料庫移轉服務沒有網際網路連線。

  • 請確定您的虛擬網路網路安全組 (NSG) 規則不會封鎖 ServiceBus、儲存體 和 AzureMonitor 的 ServiceTag 輸出埠 443。 如需虛擬網路 NSG 流量篩選的詳細資訊,請參閱<使用網路安全性群組來篩選網路流量>(機器翻譯) 一文。

  • 設定您的 Windows 防火牆以進行資料庫引擎存取

  • 開啟 Windows 防火牆以允許 Azure 資料庫移轉服務存取來源 PostgreSQL 伺服器,其預設會為 TCP 連接埠 5432。

  • 如果您是在來源資料庫前面使用防火牆設備,您可能必須新增防火牆規則,才能讓 Azure 資料庫移轉服務存取用於移轉的來源資料庫。

  • 建立適用於 PostgreSQL 的 Azure 資料庫的伺服器層級防火牆規則,以允許 Azure 資料庫移轉服務存取目標資料庫。 提供用於 Azure 資料庫移轉服務之虛擬網路的子網路範圍。

  • 叫用 CLI 的方法有兩種:

    • 在 Azure 入口網站 右上角,選取 [Cloud Shell] 按鈕:

      Azure 入口網站中的 Cloud Shell 按鈕

    • 在本機安裝和執行 CLI。 需要 CLI 2.18 或更新版本的命令行工具,才能管理此移轉所需的 Azure 資源。

      若要下載 CLI,請遵循安裝 Azure CLI 一文中的指示。 本文也會列出支援 Azure CLI 的平臺。

      若要設定 Windows 子系統 Linux 版 (WSL),請遵循 Windows 10 安裝指南中的指示

  • 編輯 postgresql.config 檔案並設定下列參數,在來源伺服器上啟用邏輯複寫:

    • wal_level = 邏輯
    • max_replication_slots = [插槽數目],建議將 設定為 五個位置
    • max_wal_senders =[並行工作數目] - max_wal_senders參數會設定可執行的並行工作數目,建議將 設定為 10 個工作

移轉範例架構

若要完成數據表架構、索引和預存程式等所有資料庫對象,我們需要從源資料庫擷取架構並套用至資料庫。

  1. 使用 pg_dump -s 命令來建立資料庫的架構傾印檔案。

    pg_dump -O -h hostname -U db_username -d db_name -s > your_schema.sql
    

    例如,若要傾印架構檔案 dvdrental 資料庫:

    pg_dump -O -h localhost -U postgres -d dvdrental -s  > dvdrentalSchema.sql
    

    如需使用 pg_dump 公用程式的詳細資訊,請參閱 pg-dump 教學課程中的範例。

  2. 在您的目標環境中建立空的資料庫,這是 適用於 PostgreSQL 的 Azure 資料庫。

    如需如何連線及建立資料庫的詳細資訊,請參閱在 Azure 入口網站 中建立 適用於 PostgreSQL 的 Azure 資料庫 伺服器或建立 Azure 入口網站 中的 適用於 PostgreSQL 的 Azure 資料庫 - 超大規模資料庫 (Citus) 伺服器一文。

  3. 將架構匯入至您藉由還原架構傾印檔案所建立的目標資料庫。

    psql -h hostname -U db_username -d db_name < your_schema.sql 
    

    例如:

    psql -h mypgserver-20170401.postgres.database.azure.com  -U postgres -d dvdrental < dvdrentalSchema.sql
    

注意

移轉服務會在內部處理外鍵和觸發程式的啟用/停用,以確保可靠且健全的數據遷移。 因此,您不必擔心對目標資料庫架構進行任何修改。

使用 Azure CLI 布建 DMS 實例

  1. 安裝 dms 同步擴充功能:

    • 執行下列命令來登入 Azure:

      az login
      
    • 出現提示時,請開啟網頁瀏覽器,然後輸入程式代碼來驗證您的裝置。 依照所列的指示操作。

    • PostgreSQL 在線移轉現在可在一般 CLI 套件內使用(2.18.0 版和更新版本),而不需要 dms-preview 擴充功能。 如果您過去已安裝擴充功能,您可以使用下列步驟將其移除:

      • 若要檢查您是否已安裝 dms-preview 擴充功能,請執行下列命令:

        az extension list -o table
        
      • 如果 dms-preview 已安裝擴充功能,請執行下列命令來卸載它:

        az extension remove --name dms-preview
        
      • 若要確認您已正確卸載延伸 dms-preview 模組,請執行下列命令,而且您不應該在清單中看到 dms-preview 延伸模組:

        az extension list -o table
        

      重要

      dms-preview Azure DMS 支援的其他移轉路徑仍可能需要擴充功能。 請檢查特定移轉路徑的檔,以判斷是否需要擴充功能。 本文件涵蓋擴充功能的需求,特別是 PostgreSQL 在在線 適用於 PostgreSQL 的 Azure 資料庫。

    • 隨時執行下列命令,以檢視 DMS 中支援的所有命令:

      az dms -h
      
    • 如果您有多個 Azure 訂用帳戶,請執行下列命令來設定您想要用來布建 DMS 服務的實例的訂用帳戶。

      az account set -s 97181df2-909d-420b-ab93-1bff15acb6b7
      
  2. 執行下列命令來佈建 DMS 實例:

    az dms create -l <location> -n <newServiceName> -g <yourResourceGroupName> --sku-name Premium_4vCores --subnet/subscriptions/{vnet subscription id}/resourceGroups/{vnet resource group}/providers/Microsoft.Network/virtualNetworks/{vnet name}/subnets/{subnet name} –tags tagName1=tagValue1 tagWithNoValue
    

    例如,下列命令會在下列命令中建立服務:

    • 位置:美國東部2
    • 訂閱:97181df2-909d-420b-ab93-1bff15acb6b7
    • 資源組名:PostgresDemo
    • DMS 服務名稱:PostgresCLI
    az dms create -l eastus2 -g PostgresDemo -n PostgresCLI --subnet /subscriptions/97181df2-909d-420b-ab93-1bff15acb6b7/resourceGroups/ERNetwork/providers/Microsoft.Network/virtualNetworks/AzureDMS-CORP-USC-VNET-5044/subnets/Subnet-1 --sku-name Premium_4vCores
    

    建立 DMS 服務的實例大約需要 10-12 分鐘的時間。

  3. 若要識別 DMS 代理程式的 IP 位址,以便您將它新增至 Postgres pg_hba.conf 檔案,請執行下列命令:

    az network nic list -g <ResourceGroupName>--query '[].ipConfigurations | [].privateIpAddress'
    

    例如:

    az network nic list -g PostgresDemo --query '[].ipConfigurations | [].privateIpAddress'
    

    您應該會收到類似下列位址的結果:

    [
      "172.16.136.18"
    ]
    
  4. 將 DMS 代理程式的 IP 位址新增至 Postgres pg_hba.conf 檔案。

    • 在 DMS 中完成布建之後,請記下 DMS IP 位址。

    • 將IP位址新增至來源上的 pg_hba.conf 檔案,類似於下列專案:

      host     all            all        172.16.136.18/10    md5
      host     replication    postgres   172.16.136.18/10    md5
      
  5. 接下來,執行下列命令來建立PostgreSQL移轉專案:

    az dms project create -l <location> -g <ResourceGroupName> --service-name <yourServiceName> --source-platform PostgreSQL --target-platform AzureDbforPostgreSQL -n <newProjectName>
    

    例如,下列命令會使用這些參數建立專案:

    • 位置:美國中西部
    • 資源組名:PostgresDemo
    • 服務名稱:PostgresCLI
    • 項目名稱:PGMigration
    • 來源平臺:PostgreSQL
    • 目標平臺:AzureDbForPostgreSql
    az dms project create -l westcentralus -n PGMigration -g PostgresDemo --service-name PostgresCLI --source-platform PostgreSQL --target-platform AzureDbForPostgreSql
    
  6. 使用下列步驟建立 PostgreSQL 移轉工作。

    此步驟包括使用來源IP、UserID和密碼、目的地IP、UserID、密碼和工作類型來建立連線。

    • 若要檢視選項的完整清單,請執行 命令:

      az dms project task create -h
      

      針對來源和目標連線,輸入參數會參考具有物件清單的 json 檔案。

      PostgreSQL 連線的連接 JSON 物件格式。

      {
          // if this is missing or null, you will be prompted
          "userName": "user name",
          // if this is missing or null (highly recommended) you will  be prompted  
          "password": null,
          "serverName": "server name",
          // if this is missing, it will default to the 'postgres' database
          "databaseName": "database name",
          // if this is missing, it will default to 5432 
          "port": 5432                
      }
      

      另外還有列出 json 對象的資料庫選項 json 檔案。 針對 PostgreSQL,資料庫選項 JSON 物件的格式如下所示:

      [
          {
              "name": "source database",
              "target_database_name": "target database",
              "selectedTables": [
                  "schemaName1.tableName1",
                  ...n
              ]
          },
          ...n
      ]
      
    • 若要建立來源連線 json,請開啟 記事本 並複製下列 json,並將其貼到檔案中。 根據來源伺服器修改檔案之後,請將檔案儲存在 C:\DMS\source.json中。

      {
          "userName": "postgres",    
          "password": null,
          "serverName": "13.51.14.222",
          "databaseName": "dvdrental", 
          "port": 5432                
      }
      
    • 若要建立目標連線 json,請開啟 記事本 並複製下列 json,並將它貼到檔案中。 根據目標伺服器修改檔案之後,請將檔案儲存在 C:\DMS\target.json中。

      {
          "userName": " dms@builddemotarget",    
          "password": null,           
          "serverName": " builddemotarget.postgres.database.azure.com",
          "databaseName": "inventory", 
          "port": 5432                
      }
      
    • 建立資料庫選項 json 檔案,其中列出要移轉之資料庫的清查和對應:

      • 建立要移轉的數據表清單,或使用 SQL 查詢從源資料庫產生清單。 以下提供用來產生數據表清單的範例查詢,就像範例一樣。 如果使用此查詢,請記得移除姓氏結尾的最後一個逗號,使其成為有效的 JSON 陣列。

        SELECT
            FORMAT('%s,', REPLACE(FORMAT('%I.%I', schemaname, tablename), '"', '\"')) AS SelectedTables
        FROM 
            pg_tables
        WHERE 
            schemaname NOT IN ('pg_catalog', 'information_schema');
        
      • 使用來源和目標資料庫名稱和要移轉之所選數據表清單的每個資料庫,建立資料庫選項 json 檔案,其中一個專案各有一個專案。 您可以使用上述 SQL 查詢的輸出來填入 「selectedTables」 陣列。 請注意,如果選取的數據表清單是空的,則服務會包含具有相符架構和數據表名稱的所有移轉數據表。

        [
            {
                "name": "dvdrental",
                "target_database_name": "dvdrental",
                "selectedTables": [
                    "schemaName1.tableName1",
                    "schemaName1.tableName2",                    
                    ...
                    "schemaNameN.tableNameM"
                ]
            },
            ... n
        ]
        
    • 執行下列命令,其會接受來源連線、目標連線和資料庫選項 json 檔案。

      az dms project task create -g PostgresDemo --project-name PGMigration --source-connection-json c:\DMS\source.json --database-options-json C:\DMS\option.json --service-name PostgresCLI --target-connection-json c:\DMS\target.json --task-type OnlineMigration -n runnowtask    
      

    此時,您已成功提交移轉工作。

  7. 若要顯示工作的進度,請執行下列命令:

    • 若要查看簡短的一般工作狀態

      az dms project task show --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask
      
    • 若要查看詳細的工作狀態,包括移轉進度資訊

      az dms project task show --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask --expand output
      
    • 您也可以使用 JMESPath 查詢格式,只從展開輸出擷取 migrationState:

      az dms project task show --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask --expand output --query 'properties.output[].migrationState'
      

      在輸出中,有數個參數表示不同移轉步驟的進度。 例如,請參閱下列輸出:

      {
          "output": [
              // Database Level
              {
                  "appliedChanges": 0, // Total incremental sync applied after full load
                  "cdcDeleteCounter": 0, // Total delete operation  applied after full load
                  "cdcInsertCounter": 0, // Total insert operation applied after full load
                  "cdcUpdateCounter": 0, // Total update operation applied after full load
                  "databaseName": "inventory",
                  "endedOn": null,
                  "fullLoadCompletedTables": 2, //Number of tables completed full load
                  "fullLoadErroredTables": 0, //Number of tables that contain migration error
                  "fullLoadLoadingTables": 0, //Number of tables that are in loading status
                  "fullLoadQueuedTables": 0, //Number of tables that are in queued status
                  "id": "db|inventory",
                  "incomingChanges": 0, //Number of changes after full load
                  "initializationCompleted": true,
                  "latency": 0,
                  //Status of migration task
                  "migrationState": "READY_TO_COMPLETE", //READY_TO_COMPLETE => the database is ready for cutover
                  "resultType": "DatabaseLevelOutput",
                  "startedOn": "2018-07-05T23:36:02.27839+00:00"
              }, {
                  "databaseCount": 1,
                  "endedOn": null,
                  "id": "dd27aa3a-ed71-4bff-ab34-77db4261101c",
                  "resultType": "MigrationLevelOutput",
                  "sourceServer": "138.91.123.10",
                  "sourceVersion": "PostgreSQL",
                  "startedOn": "2018-07-05T23:36:02.27839+00:00",
                  "state": "PENDING",
                  "targetServer": "builddemotarget.postgres.database.azure.com",
                  "targetVersion": "Azure Database for PostgreSQL"
              },
              // Table 1
              {
                  "cdcDeleteCounter": 0,
                  "cdcInsertCounter": 0,
                  "cdcUpdateCounter": 0,
                  "dataErrorsCount": 0,
                  "databaseName": "inventory",
                  "fullLoadEndedOn": "2018-07-05T23:36:20.740701+00:00", //Full load completed time
                  "fullLoadEstFinishTime": "1970-01-01T00:00:00+00:00",
                  "fullLoadStartedOn": "2018-07-05T23:36:15.864552+00:00", //Full load started time
                  "fullLoadTotalRows": 10, //Number of rows loaded in full load
                  "fullLoadTotalVolumeBytes": 7056, //Volume in Bytes in full load
                  "id": "or|inventory|public|actor",
                  "lastModifiedTime": "2018-07-05T23:36:16.880174+00:00",
                  "resultType": "TableLevelOutput",
                  "state": "COMPLETED", //State of migration for this table
                  "tableName": "public.catalog", //Table name
                  "totalChangesApplied": 0 //Total sync changes that applied after full load
              },
              //Table 2
              {
                  "cdcDeleteCounter": 0,
                  "cdcInsertCounter": 50,
                  "cdcUpdateCounter": 0,
                  "dataErrorsCount": 0,
                  "databaseName": "inventory",
                  "fullLoadEndedOn": "2018-07-05T23:36:23.963138+00:00",
                  "fullLoadEstFinishTime": "1970-01-01T00:00:00+00:00",
                  "fullLoadStartedOn": "2018-07-05T23:36:19.302013+00:00",
                  "fullLoadTotalRows": 112,
                  "fullLoadTotalVolumeBytes": 46592,
                  "id": "or|inventory|public|address",
                  "lastModifiedTime": "2018-07-05T23:36:20.308646+00:00",
                  "resultType": "TableLevelOutput",
                  "state": "COMPLETED",
                  "tableName": "public.orders",
                  "totalChangesApplied": 0
              }
          ],
          // DMS migration task state
          "state": "Running", //Running => service is still listening to any changes that might come in
          "taskType": null
      }
      

完全移轉工作

資料庫已準備好在完整載入完成時進行完全移轉。 根據來源伺服器與新交易的忙碌程度而定,DMS 工作可能會在完整載入完成之後套用變更。

為了確保所有數據都已趕上,請驗證來源和目標資料庫之間的數據列計數。 例如,您可以從狀態輸出驗證下列詳細資料:

Database Level
"migrationState": "READY_TO_COMPLETE" => Status of migration task. READY_TO_COMPLETE means database is ready for cutover
"incomingChanges": 0 => Check for a period of 5-10 minutes to ensure no new incoming changes need to be applied to the target server

Table Level (for each table)
"fullLoadTotalRows": 10    => The row count matches the initial row count of the table
"cdcDeleteCounter": 0      => Number of deletes after the full load
"cdcInsertCounter": 50     => Number of inserts after the full load
"cdcUpdateCounter": 0      => Number of updates after the full load
  1. 使用下列命令執行完全移轉資料庫移轉工作:

    az dms project task cutover -h
    

    例如,下列命令會起始 『Inventory』 資料庫的切入:

    az dms project task cutover --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask  --object-name Inventory
    
  2. 若要監視完全移轉進度,請執行下列命令:

    az dms project task show --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask
    
  3. 當資料庫移轉狀態顯示 [已完成] 時,請重新建立順序(如果適用),並將您的應用程式連線到新的目標實例 適用於 PostgreSQL 的 Azure 資料庫。

服務、專案、工作清除

如果您需要取消或刪除任何 DMS 工作、項目或服務,請依下列順序執行取消:

  • 取消任何執行中的工作
  • 刪除工作
  • 刪除專案
  • 刪除 DMS 服務
  1. 若要取消執行中的工作,請使用下列命令:

    az dms project task cancel --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask
    
  2. 若要刪除執行中的工作,請使用下列命令:

    az dms project task delete --service-name PostgresCLI --project-name PGMigration --resource-group PostgresDemo --name runnowtask
    
  3. 若要刪除專案,請使用下列命令:

    az dms project delete -n PGMigration -g PostgresDemo --service-name PostgresCLI
    
  4. 若要刪除 DMS 服務,請使用下列命令:

    az dms delete -g ProgresDemo -n PostgresCLI
    

下一步

  • 如需執行在線移轉至 適用於 PostgreSQL 的 Azure 資料庫 時已知問題和限制的相關信息,請參閱有關 適用於 PostgreSQL 的 Azure 資料庫 在線移轉的已知問題和因應措施一文
  • 如需 Azure 資料移轉服務 的相關信息,請參閱什麼是 Azure 資料移轉服務?一文
  • 如需 適用於 PostgreSQL 的 Azure 資料庫 的相關信息,請參閱什麼是 適用於 PostgreSQL 的 Azure 資料庫?一文