Migrar MySQL para o Banco de Dados do Azure para MySQL offline com o PowerShell & o 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 do GitHub.

Observação

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

Observação

O Amazon RDS (Serviço de Banco de Dados Relacional) para MySQL e o Amazon Aurora (baseado em MySQL) também têm suporte como fontes de migração.

Importante

Para migrações online, você pode usar ferramentas open-source, como o MyDumper/o MyLoader com a replicação de dados.

O artigo ajuda a automatizar o cenário em que os nomes de 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 que têm o mesmo nome e estrutura precisam ser migradas. Embora os artigos suponham 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 a fim de 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, também há suporte para a migração de servidores MySQL de versão inferior (v 5.6 e posterior) para versões posteriores.

Importante

As versões prévias do recurso DMS estão disponíveis no modo autoatendimento e aceitação. As versões prévias são fornecidas "no estado em que se encontram" e "conforme disponíveis" e são excluídas dos SLAs e da garantia limitada. Dessa forma, esses recursos não são destinados ao uso em produção. Para obter mais informações, consulte os Termos de uso complementares de versões prévias do Microsoft Azure.

Neste artigo, você aprenderá como:

  • Migrar esquema de banco de dados.
  • Crie um grupo de recursos.
  • Criar uma instância do Serviço de Migração de Banco de Dados do Azure.
  • Crie um projeto de migração em uma instância do Serviço de Migração de Banco de Dados do Azure.
  • Configurar 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:

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

  • Ter um banco de dados MySQL local com a versão 5.6 ou posterior. Se não tiver, baixe e instale o MySQL community edition 5.6 ou posterior.

  • Criar uma instância no Banco de Dados do Azure para MySQL. Confira o artigo Usar o MySQL Workbench para se conectar e consultar dados a fim de obter detalhes sobre como se conectar e criar um banco de dados usando o aplicativo do Workbench. A versão do Banco de Dados do Azure para MySQL deve ser igual ou maior que a versão do MySQL local. Por exemplo, o MySQL 5.7 pode migrar para o Banco de Dados do Azure para MySQL 5.7 ou atualizado para 8.

  • Criar 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 aos servidores de origem locais por meio do ExpressRoute ou da VPN. Para obter mais informações sobre como criar uma rede virtual, confira a Documentação da Rede Virtual e, especificamente, os artigos de Início Rápido com detalhes passo a passo.

    Observação

    Durante a configuração da rede virtual, se você usar o ExpressRoute com emparelhamento de rede com a Microsoft, adicione o ponto de extremidade de serviço do Microsoft.Sql à sub-rede na qual o serviço será provisionado. Essa configuração é necessária porque o Serviço de Migração de Banco de Dados do Azure não tem conectividade com a internet.

  • Verifique se as regras do grupo de segurança da rede virtual não bloqueiam a porta de saída 443 de ServiceTag para Armazenamento e AzureMonitor. Para obter mais detalhes sobre a filtragem de tráfego do NSG da rede virtual, confira o artigo Filtrar o tráfego de rede com grupos de segurança de rede.

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

  • Ao usar um dispositivo de firewall na frente de seus bancos de dados de origem, talvez seja necessário adicionar regras de firewall para permitir que as conexões do Serviço de Migração de Banco de Dados do Azure acessem os bancos 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 da VNet para o Banco de Dados do Azure para MySQL de destino a fim de permitir o acesso da Rede virtual do Serviço de Migração de Banco de Dados do Azure aos bancos de dados de destino.

  • O MySQL de origem deve estar no MySQL community edition com suporte. Para determinar a versão da instância do MySQL, execute o seguinte comando no utilitário MySQL ou no MySQL Workbench:

    SELECT @@version;
    
  • O Banco de Dados do Azure para MySQL dá suporte somente a tabelas do InnoDB. Para converter tabelas do MyISAM para o InnoDB, consulte o artigo Converter tabelas do MyISAM para o InnoDB

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

  • O guia usa o PowerShell v 7.2, que pode ser instalado de acordo com o guia de instalação

  • Baixe e instale os módulos a seguir da Galeria do PowerShell usando o cmdlet Install-Module PowerShell; não se esqueça 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 procedimentos armazenados, índices e esquemas de tabela, é necessário extrair o esquema do banco de dados de origem e aplicar ao banco de dados de destino. Para extrair o esquema, você pode usar mysqldump com o parâmetro --no-data. Para isso, você precisa de um computador que possa se conectar ao banco de dados MySQL de origem e ao Banco de Dados do Azure para MySQL de destino.

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 no Banco de Dados do Azure para MySQL de destino, 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 é necessário remover chaves estrangeiras durante a migração de esquema.

Se houver gatilhos no banco de dados, eles poderão impor a integridade de dados no destino à frente da migração de dados total da origem. A recomendação é desabilitar gatilhos em todas as tabelas no destino durante a migração e habilitá-los depois que a migração for feita.

Execute o script a seguir no MySQL Workbench no banco de dados de destino para extrair o script de remover gatilho e de adicionar gatilho.

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 de remover gatilho gerada (coluna DropQuery) no resultado para remover gatilhos no banco de dados de destino. A consulta para adicionar gatilho pode ser salva a fim de ser usada após a conclusão da migração de dados.

Fazer logon em sua assinatura do Microsoft Azure

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

O script a seguir define a assinatura padrão para a sessão do PowerShell após o logon 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
    }
}

Registrar o provedor 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 contêiner lógico no qual os recursos do Azure são implantados e gerenciados. Crie um grupo de recursos antes de criar recursos do 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 abaixo da 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 Serviço de Migração de Banco de Dados do Azure

Crie uma instância do Serviço de Migração de Banco de Dados do Azure usando o comando New-AzDataMigrationService. Esse comando espera os seguintes parâmetros obrigatórios:

  • Nome do Grupo de Recursos do Azure. Use o comando New-AzResourceGroup para criar o grupo de recursos do Azure, como mostrado anteriormente, e forneça o nome dele 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
  • Local. Especifica o local do serviço. Especifique um local de data center do Azure, como Oeste dos EUA ou Sudeste Asiático
  • Sku. Esse parâmetro corresponde ao nome do SKU do DMS. Os nomes de SKU com suporte no momento 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 denominada default, criando 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 de Informações de Conexão de Banco de Dados para as conexões de origem e destino

Depois de criar o projeto de migração, você criará as informações de conexão de 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 do MySQL de origem e de destino, criando os objetos de informações de conexão. O script solicita que o usuário insira a senha para as instâncias do MySQL de origem e de destino. Para scripts silenciosos, as credenciais podem ser buscadas no 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."

Extraia a lista de nomes de tabela do banco de dados de destino

A lista de tabelas de 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 a validação e o mapeamento apropriados possam ser feitos.

O script a seguir usa os nomes dos bancos de dados de origem e de destino e 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 de nome da tabela, mas pressupõe-se que a estrutura (contagem de colunas, nomes de colunas, tipos de dados etc.) das tabelas mapeadas seja exatamente a mesma.

O script a seguir cria um mapeamento com base na lista de destino e tabela de origem extraídas na Etapa 7. Para o carregamento de dados parcial, o usuário pode fornecer uma lista de tabelas 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 existe uma tabela com o mesmo nome na origem 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, os nomes de banco de dados e o 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

Como parte do módulo do 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.

Observação

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

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

O script a seguir usa os valores de usuário dos parâmetros e os define 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;

Criar e executar a tarefa de migração

Depois de configurar a entrada para a tarefa, esta 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
}

Excluir 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, de modo que a instância criada pode ser reutilizada. Se você não continuar a usar o Serviço de Migração de Banco de Dados, poderá 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 os projetos associados.

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

Próximas etapas