使用 PowerShell 與 Azure Database 移轉服務將 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 (以 MySQL 為基礎) 的 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 為您的內部部署來源伺服器提供站對站連線能力。 如需建立虛擬網路的詳細資訊,請參閱虛擬網路文件,特別是快速入門文章,裡面會提供逐步操作詳細資料。

    注意

    在虛擬 networkNet 設定期間,如果您使用 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 訂用帳戶

依照使用 Azure PowerShell 登入一文的指示,使用 PowerShell Connect-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_1vCoreStandard_2vCoresStandard_4vCoresPremium_4vCores

  • 虛擬子網路識別碼。 您可以使用 Get-AzVirtualNetworkSubnetConfig 命令來取得子網路的資訊。

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

# 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 資料庫移轉服務執行個體之後,您將建立移轉專案。 移轉專案會指定需要完成的移轉類型。

下列指令碼會在步驟 4 中建立的資料庫移轉服務執行個體下和相同區域中,建立名為 myfirstmysqlofflineproject 的移轉專案,以便從 MySQL 離線移轉至適用於 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 Key Vault 擷取認證。

# 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)