Migrar o MySQL para o Banco de Dados do Azure para MySQL offline com o PowerShell & Serviço de Migração de Banco de Dados do Azure

Neste artigo, você migra um banco de dados MySQL restaurado para uma instância local para o Banco de Dados do Azure para MySQL usando o recurso de migração offline do Serviço de Migração de Banco de Dados do Azure por meio do Microsoft Azure PowerShell. O artigo documenta uma coleção de scripts do PowerShell que podem ser executados em sequência para executar a migração offline do banco de dados MySQL para o Azure. Você pode baixar o script completo do PowerShell descrito neste tutorial em nosso repositório GitHub.

Nota

Atualmente, não é possível executar a migração completa do banco de dados usando o módulo Az.DataMigration. Enquanto isso, o script PowerShell de exemplo é fornecido "no estado em que se encontra" e usa a API REST do DMS e permite automatizar a migração. Esse script será modificado ou preterido, assim que o suporte oficial for adicionado no módulo Az.DataMigration e na CLI do Azure.

Nota

O Amazon Relational Database Service (RDS) para MySQL e o Amazon Aurora (baseado em MySQL) também são suportados como fontes de migração.

Importante

Para migrações online, você pode usar ferramentas de código aberto como MyDumper/MyLoader com replicação de dados.

O artigo ajuda a automatizar o cenário em que os nomes dos bancos de dados de origem e de destino podem ser iguais ou diferentes e, como parte da migração, todas ou algumas das tabelas no banco de dados de destino precisam ser migradas, que têm o mesmo nome e estrutura de tabela. Embora os artigos assumam que a origem seja uma instância de banco de dados MySQL e o destino seja o Banco de Dados do Azure para MySQL, ele pode ser usado para migrar de um Banco de Dados do Azure para MySQL para outro apenas alterando o nome e as credenciais do servidor de origem. Além disso, a migração de servidores MySQL de versão inferior (v5.6 e superior) para versões superiores também é suportada.

Importante

Os recursos de visualização do DMS estão disponíveis em uma base de autosserviço e aceitação. As visualizações prévias são fornecidas "como estão" e "conforme disponíveis" e são excluídas dos contratos de nível de serviço e da garantia limitada. Como tal, estas funcionalidades não se destinam a utilização em produção. Para obter mais informações, consulte Termos de uso suplementares para visualizações do Microsoft Azure.

Neste artigo, vai aprender a:

  • Migrar esquema de banco de dados.
  • Crie um grupo de recursos.
  • Criar uma instância do Azure Database Migration Service.
  • Crie um projeto de migração em uma instância do Serviço de Migração de Banco de Dados do Azure.
  • Configure o projeto de migração para usar o recurso de migração offline para MySQL.
  • Executar a migração.

Pré-requisitos

Para concluir essas etapas, você precisa:

  • Ter uma conta do Azure com uma assinatura ativa. Crie uma conta gratuitamente.

  • Tenha um banco de dados MySQL local com versão 5.6 ou superior. Se não, então baixe e instale o MySQL community edition 5.6 ou superior.

  • Criar uma instância na Base de Dados do Azure para MySQL. Consulte o artigo Use MySQL Workbench to connect and query data para obter detalhes sobre como conectar e criar um banco de dados usando o aplicativo Workbench. O Banco de Dados do Azure para a versão MySQL deve ser igual ou superior à versão local do MySQL. Por exemplo, o MySQL 5.7 pode migrar para o Banco de Dados do Azure para MySQL 5.7 ou atualizado para 8.

  • Crie uma Rede Virtual do Microsoft Azure para o Serviço de Migração de Banco de Dados do Azure usando o modelo de implantação do Azure Resource Manager, que fornece conectividade site a site para seus servidores de origem locais usando ExpressRoute ou VPN. Para obter mais informações sobre como criar uma rede virtual, consulte a Documentação da Rede Virtual e, especialmente, os artigos de início rápido com detalhes passo a passo.

    Nota

    Durante a configuração da rede virtual, se você usar a Rota Expressa com emparelhamento de rede para a Microsoft, adicione o ponto de extremidade do serviço Microsoft.Sql à sub-rede na qual o serviço será provisionado. Esta configuração é necessária porque o Azure Database Migration Service não tem conectividade à Internet.

  • Certifique-se de que as regras do Grupo de Segurança de Rede da rede virtual não bloqueiem a porta de saída 443 do ServiceTag for Storage e do AzureMonitor. Para obter mais detalhes sobre a filtragem de tráfego NSG de rede virtual, consulte o artigo Filtrar tráfego de rede com grupos de segurança de rede.

  • Abra o firewall do Windows para permitir conexões da Rede Virtual para o Serviço de Migração de Banco de Dados do Azure para acessar o MySQL Server de origem, que por padrão é a porta TCP 3306.

  • Ao usar um dispositivo de firewall na frente do(s) seu(s) banco(s) de dados de origem, talvez seja necessário adicionar regras de firewall para permitir que conexões da Rede Virtual para o Serviço de Migração de Banco de Dados do Azure acessem o(s) banco(s) de dados de origem para migração.

  • Crie uma regra de firewall no nível de servidor ou configure pontos de extremidade de serviço VNET para o Banco de Dados do Azure de destino para MySQL para permitir que a Rede Virtual para o Serviço de Migração de Banco de Dados do Azure acesse os bancos de dados de destino.

  • O MySQL de origem tem de estar na edição de comunidade do MySQL suportada. Para determinar a versão da instância do MySQL, no utilitário MySQL ou no MySQL Workbench, execute o seguinte comando:

    SELECT @@version;
    
  • A Base de Dados do Azure para MySQL suporta apenas tabelas InnoDB. Para converter tabelas MyISAM para InnoDB, veja o artigo Converting Tables from MyISAM to InnoDB (Converter Tabelas de MyISAM para InnoDB)

  • O usuário deve ter os privilégios para ler dados no banco de dados de origem.

  • O guia usa o PowerShell v7.2, que pode ser instalado de acordo com o guia de instalação

  • Baixe e instale os seguintes módulos da Galeria do PowerShell usando o cmdlet Install-Module PowerShell; certifique-se de abrir a janela de comando do PowerShell usando executar como administrador:

    • 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

Migrar esquema de banco de dados

Para transferir todos os objetos de banco de dados, como esquemas de tabela, índices e procedimentos armazenados, precisamos extrair o esquema do banco de dados de origem e aplicar ao banco de dados de destino. Para extrair o esquema, pode utilizar mysqldump com o parâmetro --no-data. Para isso, você precisa de uma máquina que possa se conectar ao banco de dados MySQL de origem e ao Banco de Dados do Azure de destino para MySQL.

Para exportar o esquema usando mysqldump, execute o seguinte comando:

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

Por exemplo:

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

Para importar o esquema para o Banco de Dados do Azure de destino para MySQL, execute o seguinte comando:

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

Por exemplo:

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

Se você tiver chaves estrangeiras em seu esquema, a carga de dados paralela durante a migração será tratada pela tarefa de migração. Não há necessidade de soltar chaves estrangeiras durante a migração do esquema.

Se você tiver gatilhos no banco de dados, ele imporá a integridade dos dados no destino antes da migração completa de dados da origem. A recomendação é desabilitar os gatilhos em todas as tabelas no destino durante a migração e, em seguida, habilitar os gatilhos após a migração.

Execute o seguinte script no MySQL Workbench no banco de dados de destino para extrair o script drop trigger e adicionar trigger script.

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

Execute a consulta drop trigger gerada (coluna DropQuery) no resultado para soltar gatilhos no banco de dados de destino. A consulta add trigger pode ser salva, para ser usada após a conclusão da migração de dados.

Inicie sessão na sua subscrição do Microsoft Azure

Use o comando Connect-AzAccount PowerShell para entrar em sua assinatura do Azure usando o PowerShell, de acordo com as instruções no artigo Entrar com o Azure PowerShell.

O script a seguir define a assinatura padrão para o logon pós-sessão da sessão do PowerShell e cria uma função de log auxiliar para logs de console formatados.

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

Registe o fornecedor de recursos Microsoft.DataMigration

O registro do provedor de recursos precisa ser feito em cada assinatura do Azure apenas uma vez. Sem o registro, você não poderá criar uma instância do Serviço de Migração de Banco de Dados do Azure.

Registre o provedor de recursos usando o comando Register-AzResourceProvider . O script a seguir registra o provedor de recursos necessário para o Serviço de Migração de Banco de Dados do Azure

Register-AzResourceProvider -ProviderNamespace Microsoft.DataMigration

Criar um grupo de recursos

Um grupo de recursos do Azure é um contentor lógico no qual os recursos do Azure são implementados e geridos. Crie um grupo de recursos antes de criar qualquer recurso DMS.

Crie um grupo de recursos usando o comando New-AzResourceGroup .

O exemplo a seguir cria um grupo de recursos chamado myResourceGroup na região Oeste dos EUA 2 sob a assinatura padrão 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." }

Criar uma instância do Azure Database Migration Service

Você pode criar uma nova instância do Serviço de Migração de Banco de Dados do Azure usando o comando New-AzDataMigrationService . Este comando espera os seguintes parâmetros necessários:

  • Nome do Grupo de Recursos do Azure. Você pode usar o comando New-AzResourceGroup para criar o grupo de Recursos do Azure, conforme mostrado anteriormente, e fornecer seu nome como um parâmetro.
  • Nome do serviço. Cadeia de caracteres que corresponde ao nome de serviço exclusivo desejado para o Serviço de Migração de Banco de Dados do Azure
  • Localização. Especifica o local do serviço. Especificar um local de data center do Azure, como Oeste dos EUA ou Sudeste Asiático
  • Sku. Este parâmetro corresponde ao nome DMS Sku. Os nomes de Sku atualmente suportados são Standard_1vCore, Standard_2vCores, Standard_4vCores Premium_4vCores.
  • Identificador de sub-rede virtual. Você pode usar o comando Get-AzVirtualNetworkSubnetConfig para obter as informações de uma sub-rede.

O script a seguir espera que a rede virtual myVirtualNetwork exista com uma sub-rede chamada padrão e, em seguida, cria um Serviço de Migração de Banco de Dados com o nome myDmService no grupo de recursos criado na Etapa 3 e na mesma região.

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

Criar um projeto de migração

Depois de criar uma instância do Serviço de Migração de Banco de Dados do Azure, você criará um projeto de migração. Um projeto de migração especifica o tipo de migração que precisa ser feito.

O script a seguir cria um projeto de migração chamado myfirstmysqlofflineproject para migração offline do MySQL para o Banco de Dados do Azure para MySQL na instância do Serviço de Migração de Banco de Dados criada na Etapa 4 e na mesma região.

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

Criar um objeto Database Connection Info para as conexões de origem e de destino

Depois de criar o projeto de migração, você criará as informações de conexão do banco de dados. Essas informações de conexão serão usadas para se conectar aos servidores de origem e de destino durante o processo de migração.

O script a seguir usa o nome do servidor, o nome de usuário e a senha para as instâncias MySQL de origem e de destino e cria os objetos de informações de conexão. O script solicita que o usuário insira a senha para as instâncias MySQL de origem e de destino. Para scripts silenciosos, as credenciais podem ser obtidas no Cofre de Chaves do 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."

Extrair a lista de nomes de tabelas do banco de dados de destino

A lista de tabelas do banco de dados pode ser extraída usando uma tarefa de migração e informações de conexão. A lista de tabelas será extraída do banco de dados de origem e do banco de dados de destino para que o mapeamento e a validação adequados possam ser feitos.

O script a seguir usa os nomes dos bancos de dados de origem e de destino e, em seguida, extrai a lista de tabelas dos bancos de dados usando a tarefa de migração 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."

Criar mapeamento de tabela com base na configuração do usuário

Como parte da configuração da tarefa de migração, você criará um mapeamento entre as tabelas de origem e de destino. O mapeamento está no nível do nome da tabela, mas a suposição é que a estrutura da tabela (contagem de colunas, nomes de colunas, tipos de dados, etc.) das tabelas mapeadas é exatamente a mesma.

O script a seguir cria um mapeamento com base na lista de tabelas de destino e de origem extraída na Etapa 7. Para carga parcial de dados, o usuário pode fornecer uma lista de tabela para filtrar as tabelas. Se nenhuma entrada do usuário for fornecida, todas as tabelas de destino serão mapeadas. O script também verifica se uma tabela com o mesmo nome existe na fonte ou não. Se o nome da tabela não existir na origem, a tabela de destino será ignorada para migração.

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

Criar e configurar as entradas da tarefa de migração

Depois de criar o mapeamento de tabela, você criará as entradas para a tarefa de migração do tipo Migrate.MySql.AzureDbForMySql e configurará as propriedades.

O script a seguir cria a tarefa de migração e define as conexões, nomes de banco de dados e mapeamento de tabela.

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

Configurar parâmetros de ajuste de desempenho

Conforme pertinente do módulo PowerShell, há alguns parâmetros opcionais disponíveis, que podem ser ajustados com base no ambiente. Esses parâmetros podem ser usados para melhorar o desempenho da tarefa de migração. Todos esses parâmetros são opcionais e seu valor padrão é NULL.

Nota

As configurações de desempenho a seguir mostraram uma taxa de transferência aumentada durante a migração no Premium SKU.

  • WriteDataRangeBatchTaskCount = 12
  • DelayProgressUpdatesInStorageInterval = 30 segundos
  • ThrottleQueryTableDataRangeTaskAtBatchCount = 36

O script a seguir usa os valores de usuário dos parâmetros e define os parâmetros nas propriedades da tarefa de migração.

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

Criando e executando a tarefa de migração

Depois de configurar a entrada para a tarefa, agora a tarefa será criada e executada no agente. O script dispara a execução da tarefa e aguarda a conclusão da migração.

O script a seguir invoca a tarefa de migração configurada e aguarda sua conclusão.

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

Excluindo o Serviço de Migração de Banco de Dados

O mesmo Serviço de Migração de Banco de Dados pode ser usado para várias migrações para que a instância, uma vez criada, possa ser reutilizada. Se você não vai continuar a usar o Serviço de Migração de Banco de Dados, então você pode excluir o serviço usando o comando Remove-AzDataMigrationService .

O script a seguir exclui a instância do Serviço de Migração de Banco de Dados do Azure e seus projetos associados.

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

Próximos passos