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

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

注意

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

注意

Amazon Relational Database Service (適用于 MySQL 的 RDS) ,也支援 Amazon (MySQL 型) 作為移轉來源。

重要

針對線上移轉,您可以使用開放原始碼工具,例如 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 Workbench 中的 MySQL 執行個體版本,請執行下列命令:

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

  • 使用者必須具有許可權,才能讀取源資料庫上的資料。

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

  • 使用Install-Module PowerShell Cmdlet從PowerShell 資源庫下載並安裝下列模組;請務必使用以系統管理員身分執行來開啟 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 訂用帳戶

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

下列腳本會設定 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 Premium_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." }

建立來源和目標連線的資料庫連接資訊物件

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

下列腳本會採用來源和目標 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
  • DelayProgressUpdatesInStorageInterval = 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)

後續步驟