使用 PowerShell 和 Azure 資料移轉服務 將 MySQL 遷移至離線 適用於 MySQL 的 Azure 資料庫

在本文中,您會使用透過 Microsoft Azure PowerShell 的離線移轉 Azure 資料移轉服務 功能,將還原至內部部署實例的 MySQL 資料庫移轉至 適用於 MySQL 的 Azure 資料庫。 本文記載了 PowerShell 腳本的集合,這些腳本可以依序執行,以執行 MySQL 資料庫的離線移轉至 Azure。 您可以從 GitHub 存放庫下載本教學課程中所述的完整 PowerShell 腳本。

注意

目前無法使用 Az.DataMigration 模組執行完整的資料庫移轉。 同時,會提供範例 PowerShell 腳本「依身分」使用 DMS REST API ,並可讓您自動移轉。 一旦 Az.DataMigration 模組和 Azure CLI 中新增官方支援,此腳本將會遭到修改或取代。

注意

MySQL 和 Amazon Aurora 的 Amazon Relational Database Service (RDS)也支援作為移轉來源。

重要

針對在線移轉,您可以使用開放原始碼工具,例如 MyDumper/MyLoader 搭配 數據傳入複寫

本文可協助自動化來源和目標資料庫名稱可以相同或不同的案例,以及移轉目標資料庫中的所有或少數數據表都必須移轉具有相同名稱和數據表結構的一部分。 雖然文章假設來源是 MySQL 資料庫實例,且目標為 適用於 MySQL 的 Azure 資料庫,但只要變更來源伺服器名稱和認證,就可以用來從一個 適用於 MySQL 的 Azure 資料庫 移轉至另一個實例。 此外,也支援從舊版 MySQL 伺服器(v5.6 和更新版本)移轉至更高版本。

重要

DMS 預覽功能是以自助式、選擇方式提供。 預覽會提供「依目前」和「可用」,且會排除在服務等級協定和有限保固之外。 因此,這些功能不適合用於生產環境。 如需詳細資訊,請參閱 Microsoft Azure 預覽版的補充使用規定。

在本文中,您將學會如何:

  • 移轉資料庫架構。
  • 建立資源群組。
  • 建立 Azure 資料移轉服務的實例。
  • 在 Azure 資料移轉服務 實例中建立移轉專案。
  • 設定移轉專案以使用 MySQL 的離線移轉功能。
  • 執行移轉。

必要條件

若要完成這些步驟,您需要:

  • 具有有效訂用帳戶的 Azure 帳戶。 免費建立帳戶

  • 具有 5.6 版或更新版本的內部部署 MySQL 資料庫。 如果沒有,請下載並安裝 MySQL 社群 5.6 版或更新版本

  • 在 適用於 MySQL 的 Azure 資料庫 中建立實例。 如需如何使用 Workbench 應用程式連線和建立資料庫的詳細資訊,請參閱使用 MySQL Workbench 連線和查詢數據一文。 適用於 MySQL 的 Azure 資料庫 版本應等於或高於內部部署 MySQL 版本。 例如,MySQL 5.7 可以遷移至 適用於 MySQL 的 Azure 資料庫 5.7 或升級至 8。

  • 使用 Azure Resource Manager 部署模型建立適用於 Azure 資料移轉服務 的 Microsoft Azure 虛擬網絡,使用 ExpressRouteVPN 提供站對站連線至內部部署來源伺服器。 如需建立虛擬網路的詳細資訊,請參閱 虛擬網絡 檔,特別是包含逐步詳細數據的快速入門文章。

    注意

    在虛擬網路網路設定期間,如果您使用 ExpressRoute 與 Microsoft 的網路對等互連,請將 Microsoft.Sql 服務 端點 新增至將佈建服務的子網。 此為必要設定,因為 Azure 資料庫移轉服務沒有網際網路連線。

  • 請確定您的虛擬網路網路安全組規則不會針對 儲存體 和 AzureMonitor 封鎖 ServiceTag 的輸出埠 443。 如需虛擬網路 NSG 流量篩選的詳細資訊,請參閱使用網路安全組篩選網路流量一文

  • 開啟 Windows 防火牆以允許來自 虛擬網絡 的連線,讓 Azure 資料移轉服務 存取來源 MySQL Server,預設為 TCP 連接埠 3306。

  • 在源資料庫前面使用防火牆設備時,您可能需要新增防火牆規則,以允許從 虛擬網絡 連線,以便 Azure 資料移轉服務 存取源資料庫進行移轉。

  • 建立伺服器層級防火牆規則,或設定目標 適用於 MySQL 的 Azure 資料庫 的 VNET 服務端點,以允許 虛擬網絡 Azure 資料移轉服務 存取目標資料庫。

  • 來源 MySQL 必須位於支援的 MySQL 社群版本上。 若要判斷 MySQL 實例的版本,請在 MySQL 公用程式或 MySQL Workbench 中執行下列命令:

    SELECT @@version;
    
  • 適用於 MySQL 的 Azure 資料庫 僅支援 InnoDB 資料表。 若要將 MyISAM 資料表轉換成 InnoDB,請參閱將數據表從 MyISAM 轉換成 InnoDB 一文

  • 用戶必須具有讀取源資料庫數據的許可權。

  • 本指南使用 PowerShell v7.2,其可依 安裝指南安裝

  • 使用 Install-Module PowerShell Cmdlet 從 PowerShell 資源庫 下載並安裝下列模組;請務必使用執行 作為 管理員 istrator 開啟 PowerShell 命令視窗:

    • Az.Resources
    • Az.Network
    • Az.DataMigration
Install-Module Az.Resources
Install-Module Az.Network
Install-Module Az.DataMigration
Import-Module Az.Resources
Import-Module Az.Network
Import-Module Az.DataMigration

移轉資料庫架構

若要傳輸數據表架構、索引和預存程式等所有資料庫對象,我們需要從源資料庫擷取架構並套用至目標資料庫。 若要擷取架構,您可以使用 mysqldump 搭配 --no-data 參數。 為此,您需要可連線到來源 MySQL 資料庫和目標 適用於 MySQL 的 Azure 資料庫 的電腦。

若要使用 mysqldump 匯出架構,請執行下列命令:

mysqldump -h [servername] -u [username] -p[password] --databases [db name] --no-data > [schema file path]

例如:

mysqldump -h 10.10.123.123 -u root -p --databases migtestdb --no-data > d:\migtestdb.sql

若要將架構匯入目標 適用於 MySQL 的 Azure 資料庫,請執行下列命令:

mysql.exe -h [servername] -u [username] -p[password] [database]< [schema file path]

例如:

mysql.exe -h mysqlsstrgt.mysql.database.azure.com -u docadmin@mysqlsstrgt -p migtestdb < d:\migtestdb.sql

如果您的架構中有外鍵,移轉期間平行數據載入將會由移轉工作處理。 在架構移轉期間不需要卸除外鍵。

如果您在資料庫中有觸發程式,它會在從來源完整數據遷移之前,在目標中強制執行數據完整性。 建議在移轉期間停用目標中所有數據表上的觸發程式,然後在移轉完成後啟用觸發程式。

在目標資料庫的 MySQL Workbench 中執行下列腳本,以擷取卸除觸發程式腳本並新增觸發程式腳本。

SELECT
    SchemaName,
    GROUP_CONCAT(DropQuery SEPARATOR ';\n') as DropQuery,
    Concat('DELIMITER $$ \n\n', GROUP_CONCAT(AddQuery SEPARATOR '$$\n'), '$$\n\nDELIMITER ;') as AddQuery
FROM
(
SELECT
    TRIGGER_SCHEMA as SchemaName,
    Concat('DROP TRIGGER `', TRIGGER_NAME, "`") as DropQuery,
    Concat('CREATE TRIGGER `', TRIGGER_NAME, '` ', ACTION_TIMING, ' ', EVENT_MANIPULATION,
            '\nON `', EVENT_OBJECT_TABLE, '`\n' , 'FOR EACH ', ACTION_ORIENTATION, ' ',
            ACTION_STATEMENT) as AddQuery
FROM
    INFORMATION_SCHEMA.TRIGGERS
ORDER BY EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION, ACTION_ORDER ASC
) AS Queries
GROUP BY SchemaName

在結果中執行產生的卸除觸發程式查詢 (DropQuery 數據行),以卸除目標資料庫中的觸發程式。 新增觸發程式查詢可以儲存,以在數據遷移完成後使用。

登入您的 Microsoft Azure 訂用帳戶

依照使用 Azure PowerShell 登入一文中的指示,使用 連線-AzAccount PowerShell 命令登入您的 Azure 訂用帳戶。

下列腳本會設定 PowerShell 工作階段登入後的預設訂用帳戶,並建立格式化控制台記錄的協助程式記錄函式。

[string] $SubscriptionName = "mySubscription"
$ErrorActionPreference = "Stop";

Connect-AzAccount
Set-AzContext -Subscription $SubscriptionName
$global:currentSubscriptionId = (Get-AzContext).Subscription.Id;

function LogMessage([string] $Message, [bool] $IsProcessing = $false) {
    if ($IsProcessing) {
        Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): $Message" -ForegroundColor Yellow
    }
    else {
        Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): $Message" -ForegroundColor Green
    }
}

註冊 Microsoft.DataMigration 資源提供者

只需要在每個 Azure 訂用帳戶上註冊資源提供者一次。 如果沒有註冊,您將無法建立 Azure 資料移轉服務實例。

使用 Register-AzResourceProvider 命令註冊資源提供者。 下列腳本會註冊 Azure 資料移轉服務 所需的資源提供者

Register-AzResourceProvider -ProviderNamespace Microsoft.DataMigration

建立資源群組

Azure 資源群組是在其中部署與管理 Azure 資源的邏輯容器。 建立任何 DMS 資源之前,請先建立資源群組。

使用 New-AzResourceGroup 命令建立資源群組。

下列範例會在預設訂用帳戶 mySubscription 下,在美國西部 2 區域中建立名為 myResourceGroup 的資源群組。

# Get the details of resource group
[string] $Location = "westus2"
[string] $ResourceGroupName = "myResourceGroup"

$resourceGroup = Get-AzResourceGroup -Name $ResourceGroupName
if (-not($resourceGroup)) {
    LogMessage -Message "Creating resource group $ResourceGroupName..." -IsProcessing $true
    $resourceGroup = New-AzResourceGroup -Name $ResourceGroupName -Location $Location
    LogMessage -Message "Created resource group - $($resourceGroup.ResourceId)."
}
else { LogMessage -Message "Resource group $ResourceGroupName exists." }

建立 Azure 資料移轉服務的實例

您可以使用 New-AzDataMigrationService 命令來建立 Azure 資料移轉服務 的新實例。 此指令需要下列必要參數:

  • Azure 資源組名。 您可以使用 New-AzResourceGroup 命令,如先前所示建立 Azure 資源群組,並提供其名稱做為參數。
  • 服務名稱。 對應至 Azure 資料移轉服務 所需唯一服務名稱的字串
  • 位置。​​ 指定服務的位置。 指定 Azure 資料中心位置,例如美國西部或東南亞
  • Sku。 此參數對應於 DMS Sku 名稱。 目前支援的 Sku 名稱是Standard_1vCore、Standard_2vCores、Standard_4vCores、進階版_4vCores。
  • 虛擬子網標識碼。 您可以使用 Get-AzVirtualNetworkSubnetConfig 命令來取得子網的資訊。

下列腳本預期 myVirtualNetwork 虛擬網路存在名為 default 的子網,然後在步驟 3 和相同區域中建立資源群組下名稱 myDmService 的 資料移轉服務。

# Get a reference to the DMS service - Create if not exists
[string] $VirtualNetworkName = "myVirtualNetwork"
[string] $SubnetName = "default"
[string] $ServiceName = "myDmService"

$dmsServiceResourceId = "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$ResourceGroupName/providers/Microsoft.DataMigration/services/$ServiceName"
$dmsService = Get-AzResource -ResourceId $dmsServiceResourceId -ErrorAction SilentlyContinue

# Create Azure DMS service if not existing
# Possible values for SKU currently are Standard_1vCore,Standard_2vCores,Standard_4vCores,Premium_4vCores
if (-not($dmsService)) {
    $virtualNetwork = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VirtualNetworkName
    if (-not ($virtualNetwork)) { throw "ERROR: Virtual Network $VirtualNetworkName does not exists" }

    $subnet = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $virtualNetwork -Name $SubnetName
    if (-not ($subnet)) { throw "ERROR: Virtual Network $VirtualNetworkName does not contains Subnet $SubnetName" }

    LogMessage -Message "Creating Azure Data Migration Service $ServiceName..." -IsProcessing $true
    $dmsService = New-AzDataMigrationService `
        -ResourceGroupName $ResourceGroupName `
        -Name $ServiceName `
        -Location $resourceGroup.Location `
        -Sku Premium_4vCores `
        -VirtualSubnetId $Subnet.Id

    $dmsService = Get-AzResource -ResourceId $dmsServiceResourceId
    LogMessage -Message "Created Azure Data Migration Service - $($dmsService.ResourceId)."
}
else { LogMessage -Message "Azure Data Migration Service $ServiceName exists." }

建立移轉專案

建立 Azure 資料移轉服務 實例之後,您將建立移轉專案。 移轉專案會指定需要完成的移轉類型。

下列腳本會建立名為 myfirstmysqlofflineproject 的移轉專案,以便從 MySQL 離機移轉至在步驟 4 和相同區域中建立的 資料移轉服務 實例下 適用於 MySQL 的 Azure 資料庫。

# Get a reference to the DMS project - Create if not exists
[string] $ProjectName = "myfirstmysqlofflineproject"

$dmsProjectResourceId = "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$($dmsService.ResourceGroupName)/providers/Microsoft.DataMigration/services/$($dmsService.Name)/projects/$projectName"
$dmsProject = Get-AzResource -ResourceId $dmsProjectResourceId -ErrorAction SilentlyContinue

# Create Azure DMS Project if not existing
if (-not($dmsProject)) {
    LogMessage -Message "Creating Azure DMS project $projectName for MySQL migration ..." -IsProcessing $true

    $newProjectProperties = @{"sourcePlatform" = "MySQL"; "targetPlatform" = "AzureDbForMySQL" }
    $dmsProject = New-AzResource `
        -ApiVersion 2018-03-31-preview `
        -Location $dmsService.Location `
        -ResourceId $dmsProjectResourceId `
        -Properties $newProjectProperties `
        -Force

    LogMessage -Message "Created Azure DMS project $projectName - $($dmsProject.ResourceId)."
}
else { LogMessage -Message "Azure DMS project $projectName exists." }

為來源和目標連線建立Database 連線ion Info物件

建立移轉項目之後,您將建立資料庫連接資訊。 此連線資訊將用來在移轉程式期間連線到來源和目標伺服器。

下列文本會取得來源和目標 MySQL 實例的伺服器名稱、使用者名稱和密碼,並建立連接信息物件。 腳本會提示使用者輸入來源和目標 MySQL 實例的密碼。 針對無訊息腳本,可以從 Azure 金鑰保存庫 擷取認證。

# Initialize the source and target database server connections
[string] $SourceServerName = "13.66.136.192"
[string] $SourceUserName = "docadmin@mysqlserver"
[securestring] $SourcePassword = Read-Host "Enter MySQL Source Server Password" -AsSecureString

[string] $TargetServerName = "migdocdevwus2mysqlsstrgt.mysql.database.azure.com"
[string] $TargetUserName = "docadmin@migdocdevwus2mysqlsstrgt"
[securestring] $TargetPassword = Read-Host "Enter MySQL Target Server Password" -AsSecureString

function InitConnection(
    [string] $ServerName,
    [string] $UserName,
    [securestring] $Password) {
    $connectionInfo = @{
        "dataSource"             = "";
        "serverName"             = "";
        "port"                   = 3306;
        "userName"               = "";
        "password"               = "";
        "authentication"         = "SqlAuthentication";
        "encryptConnection"      = $true;
        "trustServerCertificate" = $true;
        "additionalSettings"     = "";
        "type"                   = "MySqlConnectionInfo"
    }

    $connectionInfo.dataSource = $ServerName;
    $connectionInfo.serverName = $ServerName;
    $connectionInfo.userName = $UserName;
    $connectionInfo.password = (ConvertFrom-SecureString -AsPlainText $password).ToString();
    $connectionInfo;
}

# Initialize the source and target connections
LogMessage -Message "Initializing source and target connection objects ..." -IsProcessing $true
$sourceConnInfo = InitConnection `
    $SourceServerName `
    $SourceUserName `
    $SourcePassword;

$targetConnInfo = InitConnection `
    $TargetServerName `
    $TargetUserName `
    $TargetPassword;

LogMessage -Message "Source and target connection object initialization complete."

從目標資料庫擷取資料表名稱清單

您可以使用移轉工作和連線資訊來擷取資料庫資料表清單。 數據表清單將從源資料庫和目標資料庫擷取,以便進行適當的對應和驗證。

下列腳本會採用來源和目標資料庫的名稱,然後使用 GetUserTablesMySql 移轉工作從資料庫擷取數據表清單。

# Run scenario to get the tables from the target database to build
# the migration table mapping
[string] $TargetDatabaseName = "migtargetdb"
[string] $SourceDatabaseName = "migsourcedb"

function RunScenario([object] $MigrationService,
    [object] $MigrationProject,
    [string] $ScenarioTaskName,
    [object] $TaskProperties,
    [bool] $WaitForScenario = $true) {
    # Check if the scenario task already exists, if so remove it
    LogMessage -Message "Removing scenario if already exists..." -IsProcessing $true
    Remove-AzDataMigrationTask `
        -ResourceGroupName $MigrationService.ResourceGroupName `
        -ServiceName $MigrationService.Name `
        -ProjectName $MigrationProject.Name `
        -TaskName $ScenarioTaskName `
        -Force;

    # Start the new scenario task using the provided properties
    LogMessage -Message "Initializing scenario..." -IsProcessing $true
    New-AzResource `
        -ApiVersion 2018-03-31-preview `
        -Location $MigrationService.Location `
        -ResourceId "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$($MigrationService.ResourceGroupName)/providers/Microsoft.DataMigration/services/$($MigrationService.Name)/projects/$($MigrationProject.Name)/tasks/$($ScenarioTaskName)" `
        -Properties $TaskProperties `
        -Force | Out-Null;

    LogMessage -Message "Waiting for $ScenarioTaskName scenario to complete..." -IsProcessing $true
    if ($WaitForScenario) {
        $progressCounter = 0;
        do {
            if ($null -ne $scenarioTask) {
                Start-Sleep 10;
            }

            # Get calls can time out and will return a cancellation exception in that case
            $scenarioTask = Get-AzDataMigrationTask `
                -ResourceGroupName $MigrationService.ResourceGroupName `
                -ServiceName $MigrationService.Name `
                -ProjectName $MigrationProject.Name `
                -TaskName $ScenarioTaskName `
                -Expand `
                -ErrorAction Ignore;

            Write-Progress -Activity "Scenario Run $ScenarioTaskName  (Marquee Progress Bar)" `
                -Status $scenarioTask.ProjectTask.Properties.State `
                -PercentComplete $progressCounter

            $progressCounter += 10;
            if ($progressCounter -gt 100) { $progressCounter = 10 }
        }
        while (($null -eq $scenarioTask) -or ($scenarioTask.ProjectTask.Properties.State -eq "Running") -or ($scenarioTask.ProjectTask.Properties.State -eq "Queued"))
    }
    Write-Progress -Activity "Scenario Run $ScenarioTaskName" `
        -Status $scenarioTask.ProjectTask.Properties.State `
        -Completed

    # Now get it using REST APIs so we can expand the output
    LogMessage -Message "Getting expanded task results ..." -IsProcessing $true
    $psToken = (Get-AzAccessToken -ResourceUrl https://management.azure.com).Token;
    $token = ConvertTo-SecureString -String $psToken -AsPlainText -Force;
    $taskResource = Invoke-RestMethod `
        -Method GET `
        -Uri "https://management.azure.com$($scenarioTask.ProjectTask.Id)?api-version=2018-03-31-preview&`$expand=output" `
        -ContentType "application/json" `
        -Authentication Bearer `
        -Token $token;

    $taskResource.properties;
}

# create the get table task properties by initializing the connection and
# database name
$getTablesTaskProperties = @{
    "input"    = @{
        "connectionInfo"    = $null;
        "selectedDatabases" = $null;
    };
    "taskType" = "GetUserTablesMySql";
};

LogMessage -Message "Running scenario to get the list of tables from the target database..." -IsProcessing $true
$getTablesTaskProperties.input.connectionInfo = $targetConnInfo;
$getTablesTaskProperties.input.selectedDatabases = @($TargetDatabaseName);
# Create a name for the task
$getTableTaskName = "$($TargetDatabaseName)GetUserTables"
# Get the list of tables from the source
$getTargetTablesTask = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $getTableTaskName `
    -TaskProperties $getTablesTaskProperties;

if (-not ($getTargetTablesTask)) { throw "ERROR: Could not get target database $TargetDatabaseName table information." }
LogMessage -Message "List of tables from the target database acquired."

LogMessage -Message "Running scenario to get the list of tables from the source database..." -IsProcessing $true
$getTablesTaskProperties.input.connectionInfo = $sourceConnInfo;
$getTablesTaskProperties.input.selectedDatabases = @($SourceDatabaseName);
# Create a name for the task
$getTableTaskName = "$($SourceDatabaseName)GetUserTables"
# Get the list of tables from the source
$getSourceTablesTask = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $getTableTaskName `
    -TaskProperties $getTablesTaskProperties;

if (-not ($getSourceTablesTask)) { throw "ERROR: Could not get source database $SourceDatabaseName table information." }
LogMessage -Message "List of tables from the source database acquired."

根據使用者設定建置數據表對應

在設定移轉工作的一部分,您將建立來源和目標數據表之間的對應。 對應位於數據表名稱層級,但假設對應數據表的數據表結構(數據行計數、數據行名稱、數據類型等)完全相同。

下列腳本會根據步驟 7擷取的目標和源數據表清單建立對應。 針對部分數據載入,使用者可以提供資料表清單來篩選掉數據表。 如果未提供任何使用者輸入,則會對應所有目標數據表。 腳本也會檢查來源中是否有具有相同名稱的數據表。 如果來源中沒有數據表名稱,則會忽略目標數據表以進行移轉。

# Create the source to target table map
# Optional table settings
# DEFAULT: $IncludeTables = $null => include all tables for migration
# DEFAULT: $ExcludeTables = $null => exclude no tables from migration
# Exclude list has higher priority than include list
# Array of qualified source table names which should be migrated
[string[]] $IncludeTables = @("migsourcedb.coupons", "migsourcedb.daily_cash_sheets");
[string[]] $ExcludeTables = $null;

LogMessage -Message "Creating the table map based on the user input and database table information ..." `
    -IsProcessing $true

$targetTables = $getTargetTablesTask.Output.DatabasesToTables."$TargetDatabaseName";
$sourceTables = $getSourceTablesTask.Output.DatabasesToTables."$SourceDatabaseName";
$tableMap = New-Object 'system.collections.generic.dictionary[string,string]';

$schemaPrefixLength = $($SourceDatabaseName + ".").Length;
$tableMappingError = $false
foreach ($srcTable in $sourceTables) {
    # Removing the database name prefix from the table name so that comparison
    # can be done in cases where database name given are different
    $tableName = $srcTable.Name.Substring($schemaPrefixLength, `
            $srcTable.Name.Length - $schemaPrefixLength)

    # In case the table is part of exclusion list then ignore the table
    if ($null -ne $ExcludeTables -and $ExcludeTables -contains $srcTable.Name) {
        continue;
    }

    # Either the include list is null or the table is part of the include list then add it in the mapping
    if ($null -eq $IncludeTables -or $IncludeTables -contains $srcTable.Name) {
        # Check if the table exists in the target. If not then log TABLE MAPPING ERROR
        if (-not ($targetTables | Where-Object { $_.name -ieq "$($TargetDatabaseName).$tableName" })) {
            $tableMappingError = $true
            Write-Host "TABLE MAPPING ERROR: $($targetTables.name) does not exists in target." -ForegroundColor Red
            continue;
        }

        $tableMap.Add("$($SourceDatabaseName).$tableName", "$($TargetDatabaseName).$tableName");
    }
}

# In case of any table mapping errors identified, throw an error and stop the process
if ($tableMappingError) { throw "ERROR: One or more table mapping errors were identified. Please see previous messages." }
# In case no tables are in the mapping then throw error
if ($tableMap.Count -le 0) { throw "ERROR: Could not create table mapping." }
LogMessage -Message "Migration table mapping created for $($tableMap.Count) tables."

建立和設定移轉工作輸入

建置數據表對應之後,您將建立 Migrate.MySql.AzureDbForMySql 類型的移轉工作的輸入,並設定屬性。

下列腳本會建立移轉工作,並設定連接、資料庫名稱和數據表對應。

# Create and configure the migration scenario based on the connections
# and the table mapping
$offlineMigTaskProperties = @{
    "input"    = @{
        "sourceConnectionInfo"  = $null;
        "targetConnectionInfo"  = $null;
        "selectedDatabases"     = $null;
        "optionalAgentSettings" = @{
            "EnableCacheBatchesInMemory"         = $true;
            "DisableIncrementalRowStatusUpdates" = $true;
        };
        "startedOn"             = $null;
    };
    "taskType" = "Migrate.MySql.AzureDbForMySql";
};
$offlineSelectedDatabase = @{
    "name"               = $null;
    "targetDatabaseName" = $null;
    "tableMap"           = $null;
};

LogMessage -Message "Preparing migration scenario configuration ..." -IsProcessing $true

# Select the database to be migrated
$offlineSelectedDatabase.name = $SourceDatabaseName;
$offlineSelectedDatabase.tableMap = New-Object PSObject -Property $tableMap;
$offlineSelectedDatabase.targetDatabaseName = $TargetDatabaseName;

# Set connection info and the database mapping
$offlineMigTaskProperties.input.sourceConnectionInfo = $sourceConnInfo;
$offlineMigTaskProperties.input.targetConnectionInfo = $targetConnInfo;
$offlineMigTaskProperties.input.selectedDatabases = @($offlineSelectedDatabase);
$offlineMigTaskProperties.input.startedOn = [System.DateTimeOffset]::UtcNow.ToString("O");

設定效能微調參數

根據 PowerShell 模組,有幾個選擇性參數可用,可根據環境進行調整。 這些參數可用來改善移轉工作的效能。 所有這些參數都是選擇性的,其預設值為 NULL。

注意

在移轉期間,下列效能設定顯示 進階版 SKU 的輸送量增加。

  • WriteDataRangeBatchTaskCount = 12
  • DelayProgress 更新 In 儲存體 Interval = 30 秒
  • ThrottleQueryTableDataRangeTaskAtBatchCount = 36

下列腳本會採用參數的使用者值,並在移轉工作屬性中設定參數。

# Setting optional parameters from fine tuning the data transfer rate during migration
# DEFAULT values for all the configurations is $null
LogMessage -Message "Adding optional migration performance tuning configuration ..." -IsProcessing $true
# Partitioning settings
# Optional setting that configures the maximum number of parallel reads on tables located on the source database.
[object] $DesiredRangesCount = 4
# Optional setting that configures that size of the largest batch that will be committed to the target server.
[object] $MaxBatchSizeKb = 4096
# Optional setting that configures the minimum number of rows in each batch written to the target.
[object] $MinBatchRows = $null
# Task count settings
# Optional setting that configures the number of databases that will be prepared for migration in parallel.
[object] $PrepareDatabaseForBulkImportTaskCount = $null
# Optional setting that configures the number of tables that will be prepared for migration in parallel.
[object] $PrepareTableForBulkImportTaskCount = $null
# Optional setting that configures the number of threads available to read ranges on the source.
[object] $QueryTableDataRangeTaskCount = 8
# Optional setting that configures the number of threads available to write batches to the target.
[object] $WriteDataRangeBatchTaskCount = 12
# Batch cache settings
# Optional setting that configures how much memory will be used to cache batches in memory before reads on the source are throttled.
[object] $MaxBatchCacheSizeMb = $null
# Optional setting that configures the amount of available memory at which point reads on the source will be throttled.
[object] $ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb = $null
# Optional setting that configures the number of batches cached in memory that will trigger read throttling on the source.
[object] $ThrottleQueryTableDataRangeTaskAtBatchCount = 36
# Performance settings
# Optional setting that configures the delay between updates of result objects in Azure Table Storage.
[object] $DelayProgressUpdatesInStorageInterval = "00:00:30"

function AddOptionalSetting($optionalAgentSettings, $settingName, $settingValue) {
    # If no value specified for the setting, don't bother adding it to the input
    if ($null -eq $settingValue) {
        return;
    }

    # Add a new property to the JSON object to capture the setting which will be customized
    $optionalAgentSettings | add-member -MemberType NoteProperty -Name $settingName -Value $settingValue
}

# Set any optional settings in the input based on parameters to this cmdlet
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "DesiredRangesCount" $DesiredRangesCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MaxBatchSizeKb" $MaxBatchSizeKb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MinBatchRows" $MinBatchRows;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "PrepareDatabaseForBulkImportTaskCount" $PrepareDatabaseForBulkImportTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "PrepareTableForBulkImportTaskCount" $PrepareTableForBulkImportTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "QueryTableDataRangeTaskCount" $QueryTableDataRangeTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "WriteDataRangeBatchTaskCount" $WriteDataRangeBatchTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MaxBatchCacheSizeMb" $MaxBatchCacheSizeMb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb" $ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "ThrottleQueryTableDataRangeTaskAtBatchCount" $ThrottleQueryTableDataRangeTaskAtBatchCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "DelayProgressUpdatesInStorageInterval" $DelayProgressUpdatesInStorageInterval;

建立和執行移轉工作

設定工作的輸入之後,現在會在代理程式上建立並執行工作。 腳本會觸發工作執行,並等候移轉完成。

下列腳本會叫用已設定的移轉工作,並等候其完成。

# Running the migration scenario
[string] $TaskName = "mysqlofflinemigrate"

LogMessage -Message "Running data migration scenario ..." -IsProcessing $true
$summary = @{
    "SourceServer"   = $SourceServerName;
    "SourceDatabase" = $SourceDatabaseName;
    "TargetServer"   = $TargetServerName;
    "TargetDatabase" = $TargetDatabaseName;
    "TableCount"     = $tableMap.Count;
    "StartedOn"      = $offlineMigTaskProperties.input.startedOn;
}

Write-Host "Job Summary:" -ForegroundColor Yellow
Write-Host $(ConvertTo-Json $summary) -ForegroundColor Yellow

$migrationResult = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $TaskName `
    -TaskProperties $offlineMigTaskProperties

LogMessage -Message "Migration completed with status - $($migrationResult.state)"
#Checking for any errors or warnings captured by the task during migration
$dbLevelResult = $migrationResult.output | Where-Object { $_.resultType -eq "DatabaseLevelOutput" }
$migrationLevelResult = $migrationResult.output | Where-Object { $_.resultType -eq "MigrationLevelOutput" }
if ($dbLevelResult.exceptionsAndWarnings) {
    Write-Host "Following database errors were captured: $($dbLevelResult.exceptionsAndWarnings)" -ForegroundColor Red
}
if ($migrationLevelResult.exceptionsAndWarnings) {
    Write-Host "Following migration errors were captured: $($migrationLevelResult.exceptionsAndWarnings)" -ForegroundColor Red
}
if ($migrationResult.errors.details) {
    Write-Host "Following task level migration errors were captured: $($migrationResult.errors.details)" -ForegroundColor Red
}

刪除 資料移轉服務

相同的 資料移轉服務 可用於多個移轉,以便重複使用建立後實例。 如果您不打算繼續使用 資料移轉服務,您可以使用 Remove-AzDataMigrationService 命令來刪除服務

下列文本會刪除 Azure 資料移轉服務 實例及其相關聯的專案。

Remove-AzDataMigrationService -ResourceId $($dmsService.ResourceId)

下一步

  • 如需使用 DMS 執行移轉時已知問題和限制的相關信息,請參閱常見問題 - Azure 資料移轉服務 一文
  • 如需在使用 DMS 時針對源資料庫連線問題進行疑難解答,請參閱連線源資料庫的問題一文
  • 如需 Azure 資料移轉服務 的相關信息,請參閱什麼是 Azure 資料移轉服務?一文
  • 如需 適用於 MySQL 的 Azure 資料庫 的相關信息,請參閱什麼是 適用於 MySQL 的 Azure 資料庫?一文
  • 如需透過入口網站使用 DMS 的教學課程,請參閱教學課程:使用 DMS 將 MySQL 遷移至離線 適用於 MySQL 的 Azure 資料庫 一文