Offline migrace MySQL do služby Azure Database for MySQL pomocí PowerShellu a služby Azure Database Migration Service

V tomto článku migrujete databázi MySQL obnovenou do místní instance do služby Azure Database for MySQL pomocí funkce offline migrace služby Azure Database Migration Service prostřednictvím Microsoft Azure PowerShellu. Článek dokumentuje kolekci skriptů PowerShellu, které je možné spouštět postupně za účelem provedení offline migrace databáze MySQL do Azure. Kompletní skript PowerShellu popsaný v tomto kurzu si můžete stáhnout z našeho úložiště GitHub.

Poznámka:

V současné době není možné spustit úplnou migraci databáze pomocí modulu Az.DataMigration. Do té doby je ukázkový skript PowerShellu k dispozici "tak, jak je", který používá rozhraní REST API DMS a umožňuje automatizovat migraci. Tento skript se upraví nebo přestane používat, jakmile se do modulu Az.DataMigration a Azure CLI přidá oficiální podpora.

Poznámka:

Jako zdroje pro migraci se podporují také Amazon Relational Database Service (RDS) pro MySQL a Amazon Aurora (založené na MySQL).

Důležité

Pro online migrace můžete použít opensourcové nástroje, jako je MyDumper/MyLoader s replikací dat.

Tento článek pomáhá automatizovat scénář, ve kterém můžou být názvy zdrojových a cílových databází stejné nebo odlišné a v rámci migrace je potřeba migrovat všechny nebo několik tabulek v cílové databázi, které mají stejný název a strukturu tabulek. I když články předpokládají, že zdrojem je instance databáze MySQL a cílem být Azure Database for MySQL, dá se použít k migraci z jedné služby Azure Database for MySQL na jinou, a to změnou názvu a přihlašovacích údajů zdrojového serveru. Podporuje se také migrace ze serverů MySQL nižší verze (verze 5.6 a vyšší) na vyšší verze.

Důležité

Funkce DMS ve verzi Preview jsou k dispozici na samoobslužné bázi. Verze Preview jsou poskytovány "tak, jak jsou" a "dostupné", a jsou vyloučené ze smluv o úrovni služeb a omezené záruky. Proto tyto funkce nejsou určené pro produkční použití. Další informace najdete v dodatečných podmínkách použití pro verze Preview Microsoft Azure.

V tomto článku získáte informace o těchto tématech:

  • Migrace schématu databáze
  • Vytvořte skupinu prostředků.
  • Vytvoření instance služby Azure Database Migration Service
  • Vytvořte projekt migrace v instanci služby Azure Database Migration Service.
  • Nakonfigurujte projekt migrace tak, aby používal funkci offline migrace pro MySQL.
  • Spuštění migrace

Požadavky

K provedení těchto kroků potřebujete:

  • Mít účet Azure s aktivním předplatným. Vytvoření účtu zdarma

  • Máte místní databázi MySQL s verzí 5.6 nebo vyšší. Pokud ne, stáhněte a nainstalujte si komunitní edici MySQL 5.6 nebo vyšší.

  • Vytvořte instanci ve službě Azure Database for MySQL. Podrobnosti o tom, jak se připojit a vytvořit databázi pomocí aplikace Workbench, najdete v článku Použití aplikace MySQL Workbench a dotazování na data . Verze Azure Database for MySQL by měla být stejná nebo vyšší než místní verze MySQL. MySQL 5.7 může například migrovat na Azure Database for MySQL 5.7 nebo upgradovat na verzi 8.

  • Vytvořte službu Microsoft Azure Virtual Network for Azure Database Migration Service pomocí modelu nasazení Azure Resource Manager, který poskytuje připojení typu site-to-site k místním zdrojovým serverům pomocí ExpressRoute nebo VPN. Další informace o vytváření virtuální sítě najdete v dokumentaci k virtuální síti a zejména v článcích rychlého startu s podrobnými podrobnostmi.

    Poznámka:

    Pokud během instalace virtuální sítě použijete ExpressRoute s partnerským vztahem sítě k Microsoftu, přidejte koncový bod služby Microsoft.Sql do podsítě, ve které bude služba zřízena. Tato konfigurace je nezbytná, protože Azure Database Migration Service nemá připojení k internetu.

  • Ujistěte se, že pravidla skupiny zabezpečení sítě virtuální sítě neblokují odchozí port 443 serviceTag pro službu Storage a AzureMonitor. Další podrobnosti o filtrování provozu NSG virtuální sítě najdete v článku Filtrování síťového provozu pomocí skupin zabezpečení sítě.

  • Otevřete bránu Windows Firewall a povolte připojení ze služby Azure Database Migration Service pro přístup ke zdrojovému serveru MySQL, což je ve výchozím nastavení port TCP 3306.

  • Při použití zařízení brány firewall před zdrojovými databázemi možná budete muset přidat pravidla brány firewall, která povolí připojení z virtuální sítě pro službu Azure Database Migration Service pro přístup ke zdrojovým databázím pro migraci.

  • Vytvořte pravidlo brány firewall na úrovni serveru nebo nakonfigurujte koncové body služby virtuální sítě pro cílovou službu Azure Database for MySQL, aby virtuální síť pro službu Azure Database Migration Service umožňovala přístup k cílovým databázím.

  • Zdrojová instance MySQL musí být na podporované edici MySQL Community Edition. Pokud chcete určit verzi instance MySQL, v nástroji MySQL nebo aplikaci MySQL Workbench spusťte následující příkaz:

    SELECT @@version;
    
  • Azure Database for MySQL podporuje pouze tabulky InnoDB. Informace o převodu tabulek MyISAM na tabulky InnoDB najdete v článku Převod tabulek z MyISAM na InnoDB.

  • Uživatel musí mít oprávnění ke čtení dat ve zdrojové databázi.

  • Průvodce používá PowerShell verze 7.2, který je možné nainstalovat podle průvodce instalací.

  • Pomocí rutiny PowerShellu install-Module stáhněte a nainstalujte z Galerie prostředí PowerShell následující moduly. Nezapomeňte otevřít příkazové okno PowerShellu pomocí příkazu spustit jako Správa istrator:

    • 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

Migrace schématu databáze

Abychom mohli přenést všechny databázové objekty, jako jsou schémata tabulek, indexy a uložené procedury, musíme extrahovat schéma ze zdrojové databáze a použít je pro cílovou databázi. K extrahování schématu můžete použít nástroj mysqldump s parametrem --no-data. K tomu potřebujete počítač, který se může připojit ke zdrojové databázi MySQL i cílové databázi Azure Database for MySQL.

Pokud chcete exportovat schéma pomocí mysqldump, spusťte následující příkaz:

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

Příklad:

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

Pokud chcete importovat schéma do cílové služby Azure Database for MySQL, spusťte následující příkaz:

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

Příklad:

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

Pokud máte ve schématu cizí klíče, bude úloha migrace zpracovávat paralelní načítání dat. Během migrace schématu není nutné odstraňovat cizí klíče.

Pokud máte v databázi triggery, vynutí integritu dat v cíli před úplnou migrací dat ze zdroje. Doporučuje se zakázat triggery pro všechny tabulky v cíli během migrace a po dokončení migrace triggery povolit.

Spuštěním následujícího skriptu v aplikaci MySQL Workbench v cílové databázi extrahujte skript triggeru pro odstranění a přidejte skript triggeru.

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

Ve výsledku spusťte vygenerovaný trigger aktivační dotaz (sloupec DropQuery), aby se triggery v cílové databázi zahodily. Přidat aktivační dotaz lze uložit, aby se použil po dokončení migrace dat.

Přihlášení k předplatnému Microsoft Azure

Pomocí příkazu Připojení-AzAccount PowerShell se přihlaste k předplatnému Azure pomocí PowerShellu podle pokynů v článku Přihlášení pomocí Azure PowerShellu.

Následující skript nastaví výchozí předplatné relace PowerShellu po přihlášení a vytvoří pomocnou funkci protokolování pro formátované protokoly konzoly.

[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
    }
}

Registrace poskytovatele prostředků Microsoft.DataMigration

Registraci poskytovatele prostředků je potřeba provést u každého předplatného Azure jenom jednou. Bez registrace nebudete moct vytvořit instanci služby Azure Database Migration Service.

Pomocí příkazu Register-AzResourceProvider zaregistrujte poskytovatele prostředků. Následující skript zaregistruje poskytovatele prostředků vyžadovaného pro službu Azure Database Migration Service.

Register-AzResourceProvider -ProviderNamespace Microsoft.DataMigration

Vytvoření skupiny zdrojů

Skupina prostředků Azure je logický kontejner, ve kterém se nasazují a spravují prostředky Azure. Před vytvořením prostředků DMS vytvořte skupinu prostředků.

Vytvořte skupinu prostředků pomocí příkazu New-AzResourceGroup .

Následující příklad vytvoří skupinu prostředků myResourceGroup v oblasti USA – západ 2 v rámci výchozího předplatného mySubscription.

# 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." }

Vytvoření instance služby Azure Database Migration Service

Novou instanci služby Azure Database Migration Service můžete vytvořit pomocí příkazu New-AzDataMigrationService . Tento příkaz očekává následující požadované parametry:

  • Název skupiny prostředků Azure Pomocí příkazu New-AzResourceGroup můžete vytvořit skupinu prostředků Azure, jak je znázorněno dříve, a zadat její název jako parametr.
  • Název služby. Řetězec odpovídající požadovanému jedinečnému názvu služby pro službu Azure Database Migration Service
  • Umístění: Určuje umístění služby. Zadejte umístění datového centra Azure, například USA – západ nebo Jihovýchodní Asie.
  • Skladová položka. Tento parametr odpovídá názvu skladové položky DMS. Aktuálně podporovaný název skladové položky jsou Standard_1vCore, Standard_2vCores, Standard_4vCores Premium_4vCores.
  • Identifikátor virtuální podsítě. K získání informací o podsíti můžete použít příkaz Get-AzVirtualNetworkSubnetConfig .

Následující skript očekává, že virtuální síť myVirtualNetwork existuje s výchozí podsítí a pak vytvoří službu Database Migration Service s názvem myDmService v rámci skupiny prostředků vytvořené v kroku 3 a ve stejné oblasti.

# 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." }

Vytvoření projektu migrace

Po vytvoření instance služby Azure Database Migration Service vytvoříte projekt migrace. Projekt migrace určuje typ migrace, který je potřeba provést.

Následující skript vytvoří projekt migrace s názvem myfirstmysqlofflineproject pro offline migraci z MySQL do Azure Database for MySQL v rámci instance služby Database Migration Service vytvořené v kroku 4 a ve stejné oblasti.

# 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." }

Vytvoření objektu Informace o Připojení databáze pro zdrojová a cílová připojení

Po vytvoření projektu migrace vytvoříte informace o připojení k databázi. Tyto informace o připojení se použijí k připojení ke zdrojovému a cílovému serveru během procesu migrace.

Následující skript převezme název serveru, uživatelské jméno a heslo pro zdrojové a cílové instance MySQL a vytvoří objekty s informacemi o připojení. Skript vyzve uživatele, aby zadal heslo pro zdrojové a cílové instance MySQL. U tichých skriptů je možné přihlašovací údaje načíst ze služby 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."

Extrahování seznamu názvů tabulek z cílové databáze

Seznam tabulek databáze je možné extrahovat pomocí úlohy migrace a informací o připojení. Seznam tabulek se extrahuje ze zdrojové i cílové databáze, aby bylo možné provést správné mapování a ověření.

Následující skript vezme názvy zdrojových a cílových databází a pak extrahuje seznam tabulek z databází pomocí úlohy migrace 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."

Mapování tabulek sestavení na základě konfigurace uživatele

V rámci konfigurace úlohy migrace vytvoříte mapování mezi zdrojovými a cílovými tabulkami. Mapování je na úrovni názvu tabulky, ale předpokládá se, že struktura tabulky (počet sloupců, názvy sloupců, datové typy atd.) mapovaných tabulek je úplně stejná.

Následující skript vytvoří mapování založené na cílovém a zdrojovém seznamu tabulek extrahovaném v kroku 7. V případě částečného načtení dat může uživatel zadat seznam tabulek, ze které se mají tabulky vyfiltrovat. Pokud není zadaný žádný uživatelský vstup, namapují se všechny cílové tabulky. Skript také zkontroluje, jestli ve zdroji existuje tabulka se stejným názvem. Pokud název tabulky ve zdroji neexistuje, bude cílová tabulka pro migraci ignorována.

# 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."

Vytvoření a konfigurace vstupů úloh migrace

Po vytvoření mapování tabulky vytvoříte vstupy pro úlohu migrace typu Migrate.MySql.AzureDbForMySql a nakonfigurujete vlastnosti.

Následující skript vytvoří úlohu migrace a nastaví připojení, názvy databází a mapování tabulek.

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

Konfigurace parametrů ladění výkonu

V případě modulu PowerShellu je k dispozici několik volitelných parametrů, které je možné ladit na základě prostředí. Tyto parametry lze použít ke zlepšení výkonu úlohy migrace. Všechny tyto parametry jsou volitelné a jejich výchozí hodnota je NULL.

Poznámka:

Následující konfigurace výkonu ukazují zvýšenou propustnost během migrace na skladovou položku Premium.

  • WriteDataRangeBatchTaskCount = 12
  • DelayProgress Aktualizace InStorageInterval = 30 sekund
  • ThrottleQueryTableDataRangeTaskAtBatchCount = 36

Následující skript vezme uživatelské hodnoty parametrů a nastaví parametry ve vlastnostech úlohy migrace.

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

Vytvoření a spuštění úlohy migrace

Po nakonfigurování vstupu pro úlohu se teď úloha vytvoří a spustí v agentu. Skript aktivuje provádění úlohy a počká na dokončení migrace.

Následující skript vyvolá nakonfigurovanou úlohu migrace a čeká na dokončení.

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

Odstranění služby Database Migration Service

Stejnou službu Database Migration Service je možné použít pro více migrací, aby bylo možné instanci po vytvoření znovu použít. Pokud službu Database Migration Service nebudete dál používat, můžete ji odstranit pomocí příkazu Remove-AzDataMigrationService .

Následující skript odstraní instanci služby Azure Database Migration Service a její přidružené projekty.

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

Další kroky