ترحيل MySQL إلى قاعدة بيانات Azure ل MySQL دون اتصال باستخدام خدمة ترحيل قاعدة بيانات PowerShell & Azure

في هذه المقالة، تقوم بترحيل قاعدة بيانات MySQL تمت استعادتها إلى مثيل محلي إلى Azure Database for MySQL باستخدام إمكانية الترحيل دون اتصال بخدمة ترحيل قاعدة بيانات Azure من خلال Microsoft Azure PowerShell. توثق المقالة مجموعة من برامج PowerShell النصية التي يمكن تنفيذها بالتسلسل لإجراء الترحيل دون اتصال لقاعدة بيانات MySQL إلى Azure. يمكنك تنزيل البرنامج النصي PowerShell الكامل الموضح في هذا البرنامج التعليمي من مستودع GitHub لدينا.

ملاحظة

في الوقت الحالي، لا يمكن تشغيل ترحيل قاعدة البيانات الكامل باستخدام الوحدة النمطية Az.DataMigration. في هذه الأثناء، يتم توفير نموذج البرنامج النصي PowerShell "كما هو" الذي يستخدم واجهة برمجة تطبيقات REST DMS ويسمح لك بأتمتة الترحيل. سيتم تعديل هذا البرنامج النصي أو إهماله، بمجرد إضافة الدعم الرسمي في الوحدة النمطية Az.DataMigration وAzure CLI.

ملاحظة

يتم أيضًا دعم Amazon Relational Database Service (RDS) لـ MySQL وAmazon Aurora (المستندة إلى MySQL) كمصادر للترحيل.

هام

لعمليات الترحيل عبر الإنترنت، يمكنك استخدام أدوات مفتوحة المصدر مثل MyDumper / MyLoader مع النسخ المتماثل للبيانات.

تساعد هذه المقالة في أتمتة السيناريو حيث يمكن أن تكون أسماء قاعدة البيانات المصدر والهدف متماثلة أو مختلفة وكجزء من الترحيل، يجب ترحيل كل أو القليل من الجداول الموجودة في قاعدة البيانات الهدف والتي لها نفس الاسم وبنية الجدول. على الرغم من أن المقالات تفترض أن المصدر هو مثيل قاعدة بيانات MySQL والهدف هو Azure Database for MySQL، يمكن استخدامه للترحيل من قاعدة بيانات Azure واحدة لـ MySQL إلى أخرى فقط عن طريق تغيير اسم الخادم المصدر وبيانات الاعتماد. يتم أيضًا دعم الترحيل من خوادم MySQL ذات الإصدار الأقل (الإصدار 5.6 وما فوق) إلى الإصدارات الأعلى.

هام

تتوفر ميزات معاينة DMS على أساس الخدمة الذاتية والاشتراك. يتم توفير المعاينات "كما هي" و"كما هي متوفرة"، ويتم استبعادها من اتفاقيات مستوى الخدمة والضمان المحدود. على هذا النحو، هذه الميزات ليست مخصصة للاستخدام الإنتاجي. لمزيد من المعلومات، راجع شروط الاستخدام التكميلية لمعاينات Microsoft Azure.

في هذا المقال، ستتعلم كيفية إجراء ما يلي:

  • ترحيل مخطط قاعدة البيانات.
  • إنشاء مجموعة موارد.
  • قم بإنشاء مثيل لخدمة ترحيل قاعدة بيانات Azure.
  • أنشئ مشروع ترحيل في مثيل خدمة ترحيل قاعدة بيانات Azure.
  • قم بتكوين مشروع الترحيل لاستخدام إمكانية الترحيل دون اتصال لـ MySQL.
  • تشغيل الترحيل.

المتطلبات الأساسية

لإكمال هذه الخطوات، أنت بحاجة إلى:

  • لديك حساب Azure باشتراك نشط. قم بإنشاء حساب مجانًا.

  • لديك قاعدة بيانات MySQL محلية مع الإصدار 5.6 أو أعلى. إذا لم يكن الأمر كذلك، فقم بتنزيل وتثبيت إصدار مجتمع MySQL 5.6 أو إصدار أحدث.

  • إنشاء مثيل في Azure Database for MySQL. راجع المقالة استخدام MySQL Workbench للاتصال والاستعلام عن البيانات للحصول على تفاصيل حول كيفية الاتصال وإنشاء قاعدة بيانات باستخدام تطبيق Workbench. يجب أن تكون قاعدة بيانات Azure لإصدار MySQL مساوية أو أعلى من إصدار MySQL المحلي. على سبيل المثال، يمكن لـ MySQL 5.7 الترحيل إلى Azure Database for MySQL 5.7 أو الترقية إلى 8.

  • إنشاء شبكة Microsoft Azure الظاهرية لخدمة ترحيل قاعدة بيانات Azure باستخدام نموذج توزيع Azure Resource Manager الذي يوفر اتصال موقع إلى موقع إلى الملقمات المصدر المحلي باستخدام ExpressRoute أو VPN. لمزيد من المعلومات حول إنشاء شبكة اتصال ظاهرية، راجع Virtual Network Documentationوخاصة مقالات التشغيل السريع التي تحتوي على التفاصيل خطوة بخطوة.

    ملاحظة

    أثناء إعداد الشبكة الظاهرية للشبكة، إذا كنت تستخدم ExpressRoute مع مناظرة الشبكة لـ Microsoft، فأضف Microsoft.Sqlنقطة نهاية إلى الشبكة الفرعية التي سيتم توفير الخدمة فيها. هذا التكوين ضروري لأن خدمة ترحيل قاعدة بيانات Azure تفتقر إلى الاتصال بالإنترنت.

  • تأكد من أن قواعد Network Security Group لشبكتك الظاهرية لا تحظر المنفذ الصادر 443 من ServiceTag للتخزين وAzureMonitor. لمزيد من التفاصيل حول تصفية حركة مرور NSG للشبكة الظاهرية، راجع مقالة تصفية حركة مرور الشبكة مع مجموعات أمان الشبكة.

  • افتح جدار حماية Windows للسماح بالاتصالات من الشبكة الظاهرية لخدمة ترحيل قاعدة بيانات Azure للوصول إلى خادم MySQL المصدر، والذي يكون منفذ TCP 3306 افتراضيًا.

  • عند استخدام جهاز جدار حماية أمام قاعدة (قواعد) البيانات المصدر، قد تحتاج إلى إضافة قواعد جدار الحماية للسماح بالاتصالات من الشبكة الظاهرية لخدمة ترحيل قاعدة بيانات Azure للوصول إلى قاعدة (قواعد) المصدر من أجل الترحيل.

  • أنشئ قاعدة جدار حماية على مستوى الخادم أو تكوين نقاط نهاية خدمة VNET لقاعدة بيانات Azure المستهدفة لـ MySQL للسماح للشبكة الظاهرية لخدمة ترحيل قاعدة بيانات Azure بالوصول إلى قواعد البيانات الهدف.

  • يجب أن يكون مصدر MySQL على إصدار مجتمع MySQL مدعوم. لتحديد إصدار مثيل MySQL، في الأداة المساعدة MySQL أو MySQL Workbench، قم بتشغيل الأمر التالي:

    SELECT @@version;
    
  • تدعم Azure Database for MySQL جداول InnoDB فقط. لتحويل جداول MyISAM إلى InnoDB، راجع المقالة تحويل الجداول من MyISAM إلى InnoDB

  • يجب أن يمتلك المستخدم الامتيازات لقراءة البيانات الموجودة في قاعدة البيانات المصدر.

  • يستخدم الدليل PowerShell v7.2، والذي يمكن تثبيته وفقا لدليل التثبيت

  • قم بتنزيل الوحدات النمطية التالية وتثبيتها من معرض PowerShell باستخدام Install-Module PowerShell cmdlet؛ تأكد من فتح نافذة أوامر PowerShell باستخدام تشغيل كمسؤول:

    • أ. الموارد
    • Az.Network
    • أز. ترحيل البيانات
Install-Module Az.Resources
Install-Module Az.Network
Install-Module Az.DataMigration
Import-Module Az.Resources
Import-Module Az.Network
Import-Module Az.DataMigration

ترحيل مخطط قاعدة البيانات

لنقل جميع كائنات قاعدة البيانات مثل مخططات الجدول والفهارس والإجراءات المخزنة، نحتاج إلى استخراج المخطط من قاعدة البيانات المصدر وتطبيقه على قاعدة البيانات الهدف. لاستخراج المخطط، يمكنك استخدام mysqldump مع المعلمة --no-data. لهذا تحتاج إلى جهاز يمكنه الاتصال بكل من قاعدة بيانات MySQL المصدر وقاعدة بيانات Azure المستهدفة لـ MySQL.

لتصدير المخطط باستخدام mysqldump، قم بتشغيل الأمر التالي:

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

على سبيل المثال:

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

لاستيراد مخطط لاستهداف Azure Database for MySQL، قم بتشغيل الأمر التالي:

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

على سبيل المثال:

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

إذا كان لديك مفاتيح خارجية في مخططك، فستتم معالجة تحميل البيانات الموازي أثناء الترحيل من خلال مهمة الترحيل. ليست هناك حاجة لإسقاط المفاتيح الخارجية أثناء ترحيل المخطط.

إذا كان لديك مشغلات في قاعدة البيانات، فستقوم بفرض تكامل البيانات في الهدف قبل ترحيل البيانات الكاملة من المصدر. يوصى بتعطيل المشغلات في كافة الجداول الموجودة في الهدف أثناء الترحيل، ثم تمكين المشغلات بعد إتمام الترحيل.

قم بتنفيذ البرنامج النصي التالي في MySQL Workbench على قاعدة البيانات الهدف لاستخراج البرنامج النصي لمشغل الإسقاط وإضافة البرنامج النصي للمشغل.

SELECT
    SchemaName,
    GROUP_CONCAT(DropQuery SEPARATOR ';\n') as DropQuery,
    Concat('DELIMITER $$ \n\n', GROUP_CONCAT(AddQuery SEPARATOR '$$\n'), '$$\n\nDELIMITER ;') as AddQuery
FROM
(
SELECT
    TRIGGER_SCHEMA as SchemaName,
    Concat('DROP TRIGGER `', TRIGGER_NAME, "`") as DropQuery,
    Concat('CREATE TRIGGER `', TRIGGER_NAME, '` ', ACTION_TIMING, ' ', EVENT_MANIPULATION,
            '\nON `', EVENT_OBJECT_TABLE, '`\n' , 'FOR EACH ', ACTION_ORIENTATION, ' ',
            ACTION_STATEMENT) as AddQuery
FROM
    INFORMATION_SCHEMA.TRIGGERS
ORDER BY EVENT_OBJECT_SCHEMA, EVENT_OBJECT_TABLE, ACTION_TIMING, EVENT_MANIPULATION, ACTION_ORDER ASC
) AS Queries
GROUP BY SchemaName

قم بتشغيل استعلام مشغل الإسقاط الذي تم إنشاؤه (عمود DropQuery) في النتيجة لإسقاط المشغلات في قاعدة البيانات الهدف. يمكن حفظ استعلام مشغل الإضافة، لاستخدامه بعد استكمال ترحيل البيانات.

قم بتسجيل الدخول إلى اشتراك Microsoft Azure الخاص بك

استخدم أمر Connect-AzAccount PowerShell لتسجيل الدخول إلى اشتراك Azure الخاص بك باستخدام PowerShell، وفقًا للإرشادات الواردة في المقالة تسجيل الدخول باستخدام Azure PowerShell.

يقوم البرنامج النصي التالي بتعيين الاشتراك الافتراضي لتسجيل الدخول بعد جلسة PowerShell وإنشاء وظيفة تسجيل مساعد لسجلات وحدة التحكم المنسقة.

[string] $SubscriptionName = "mySubscription"
$ErrorActionPreference = "Stop";

Connect-AzAccount
Set-AzContext -Subscription $SubscriptionName
$global:currentSubscriptionId = (Get-AzContext).Subscription.Id;

function LogMessage([string] $Message, [bool] $IsProcessing = $false) {
    if ($IsProcessing) {
        Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): $Message" -ForegroundColor Yellow
    }
    else {
        Write-Host "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss"): $Message" -ForegroundColor Green
    }
}

تسجيل موفر الموارد Microsoft.DataMigration

يجب أن يتم تسجيل موفر المورد على كل اشتراك Azure مرة واحدة فقط. بدون التسجيل، لن تتمكن من إنشاء مثيل من خدمة ترحيل قاعدة بيانات Azure.

قم بتسجيل موفر المورد باستخدام الأمر Register-AzResourceProvider. يقوم البرنامج النصي التالي بتسجيل موفر المورد المطلوب لـ Azure Database Migration Service

Register-AzResourceProvider -ProviderNamespace Microsoft.DataMigration

قم بإنشاء مجموعة موارد

مجموعة موارد Azure هي حاوية منطقية يتم بها نشر موارد Azure وإدارتها. قم بإنشاء مجموعة موارد قبل إنشاء أي موارد DMS.

قم بإنشاء مجموعة موارد باستخدام الأمر New-AzResourceGroup.

ينشئ المثال التالي مجموعة موارد باسم myResourceGroup في منطقة West US 2 ضمن الاشتراك الافتراضي 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." }

قم بإنشاء مثيل لخدمة ترحيل قاعدة بيانات Azure

يمكنك إنشاء مثيل جديد لخدمة ترحيل قاعدة بيانات Azure باستخدام الأمر New-AzDataMigrationService. يتوقع هذا الأمر المعلمات المطلوبة التالية:

  • اسم مجموعة موارد Azure. يمكنك استخدام الأمر New-AzResourceGroup لإنشاء مجموعة موارد Azure كما هو موضح سابقًا وتقديم اسمها كمعلمة.
  • اسم الخدمة. سلسلة تتوافق مع اسم الخدمة الفريد المطلوب لخدمة ترحيل قاعدة بيانات Azure
  • Location. يحدد موقع الخدمة. حدد موقع مركز بيانات Azure، مثل غرب الولايات المتحدة أو جنوب شرق آسيا
  • Sku. تتوافق هذه المعلمة مع اسم DMS Sku. اسم Sku المدعوم حاليًا هو Standard_1vCore، Standard_2vCores، Standard_4vCores، Premium_4vCores.
  • معرف الشبكة الفرعية الافتراضية. يمكنك استخدام الأمر Get-AzVirtualNetworkSubnetConfig للحصول على معلومات شبكة فرعية.

يتوقع البرنامج النصي التالي وجود شبكة myVirtualNetwork الافتراضية بشبكة فرعية تسمى default ثم يقوم بإنشاء خدمة ترحيل قاعدة البيانات باسم myDmService ضمن مجموعة الموارد التي تم إنشاؤها في الخطوة 3 وفي نفس المنطقة.

# Get a reference to the DMS service - Create if not exists
[string] $VirtualNetworkName = "myVirtualNetwork"
[string] $SubnetName = "default"
[string] $ServiceName = "myDmService"

$dmsServiceResourceId = "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$ResourceGroupName/providers/Microsoft.DataMigration/services/$ServiceName"
$dmsService = Get-AzResource -ResourceId $dmsServiceResourceId -ErrorAction SilentlyContinue

# Create Azure DMS service if not existing
# Possible values for SKU currently are Standard_1vCore,Standard_2vCores,Standard_4vCores,Premium_4vCores
if (-not($dmsService)) {
    $virtualNetwork = Get-AzVirtualNetwork -ResourceGroupName $ResourceGroupName -Name $VirtualNetworkName
    if (-not ($virtualNetwork)) { throw "ERROR: Virtual Network $VirtualNetworkName does not exists" }

    $subnet = Get-AzVirtualNetworkSubnetConfig -VirtualNetwork $virtualNetwork -Name $SubnetName
    if (-not ($subnet)) { throw "ERROR: Virtual Network $VirtualNetworkName does not contains Subnet $SubnetName" }

    LogMessage -Message "Creating Azure Data Migration Service $ServiceName..." -IsProcessing $true
    $dmsService = New-AzDataMigrationService `
        -ResourceGroupName $ResourceGroupName `
        -Name $ServiceName `
        -Location $resourceGroup.Location `
        -Sku Premium_4vCores `
        -VirtualSubnetId $Subnet.Id

    $dmsService = Get-AzResource -ResourceId $dmsServiceResourceId
    LogMessage -Message "Created Azure Data Migration Service - $($dmsService.ResourceId)."
}
else { LogMessage -Message "Azure Data Migration Service $ServiceName exists." }

إنشاء مشروع ترحيل

بعد إنشاء مثيل خدمة ترحيل قاعدة بيانات Azure، ستقوم بإنشاء مشروع ترحيل. يحدد مشروع الترحيل نوع الترحيل الذي يجب القيام به.

ينشئ البرنامج النصي التالي مشروع ترحيل باسم myfirstmysqlofflineproject للترحيل دون اتصال من MySQL إلى Azure Database for MySQL ضمن مثيل خدمة ترحيل قاعدة البيانات الذي تم إنشاؤه في الخطوة 4 وفي نفس المنطقة.

# Get a reference to the DMS project - Create if not exists
[string] $ProjectName = "myfirstmysqlofflineproject"

$dmsProjectResourceId = "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$($dmsService.ResourceGroupName)/providers/Microsoft.DataMigration/services/$($dmsService.Name)/projects/$projectName"
$dmsProject = Get-AzResource -ResourceId $dmsProjectResourceId -ErrorAction SilentlyContinue

# Create Azure DMS Project if not existing
if (-not($dmsProject)) {
    LogMessage -Message "Creating Azure DMS project $projectName for MySQL migration ..." -IsProcessing $true

    $newProjectProperties = @{"sourcePlatform" = "MySQL"; "targetPlatform" = "AzureDbForMySQL" }
    $dmsProject = New-AzResource `
        -ApiVersion 2018-03-31-preview `
        -Location $dmsService.Location `
        -ResourceId $dmsProjectResourceId `
        -Properties $newProjectProperties `
        -Force

    LogMessage -Message "Created Azure DMS project $projectName - $($dmsProject.ResourceId)."
}
else { LogMessage -Message "Azure DMS project $projectName exists." }

قم بإنشاء كائن "معلومات اتصال قاعدة البيانات" لاتصالات المصدر والهدف

بعد إنشاء مشروع الترحيل، ستقوم بإنشاء معلومات اتصال قاعدة البيانات. سيتم استخدام معلومات الاتصال هذه للاتصال بالخوادم المصدر والهدف أثناء عملية الترحيل.

يأخذ البرنامج النصي التالي اسم الخادم واسم المستخدم وكلمة المرور لمثيلات MySQL المصدر والهدف ويقوم بإنشاء كائنات معلومات الاتصال. يطالب البرنامج النصي المستخدم بإدخال كلمة المرور لمثيلات MySQL المصدر والهدف. بالنسبة إلى البرامج النصية الصامتة، يمكن جلب بيانات الاعتماد من Azure Key Vault.

# Initialize the source and target database server connections
[string] $SourceServerName = "13.66.136.192"
[string] $SourceUserName = "docadmin@mysqlserver"
[securestring] $SourcePassword = Read-Host "Enter MySQL Source Server Password" -AsSecureString

[string] $TargetServerName = "migdocdevwus2mysqlsstrgt.mysql.database.azure.com"
[string] $TargetUserName = "docadmin@migdocdevwus2mysqlsstrgt"
[securestring] $TargetPassword = Read-Host "Enter MySQL Target Server Password" -AsSecureString

function InitConnection(
    [string] $ServerName,
    [string] $UserName,
    [securestring] $Password) {
    $connectionInfo = @{
        "dataSource"             = "";
        "serverName"             = "";
        "port"                   = 3306;
        "userName"               = "";
        "password"               = "";
        "authentication"         = "SqlAuthentication";
        "encryptConnection"      = $true;
        "trustServerCertificate" = $true;
        "additionalSettings"     = "";
        "type"                   = "MySqlConnectionInfo"
    }

    $connectionInfo.dataSource = $ServerName;
    $connectionInfo.serverName = $ServerName;
    $connectionInfo.userName = $UserName;
    $connectionInfo.password = (ConvertFrom-SecureString -AsPlainText $password).ToString();
    $connectionInfo;
}

# Initialize the source and target connections
LogMessage -Message "Initializing source and target connection objects ..." -IsProcessing $true
$sourceConnInfo = InitConnection `
    $SourceServerName `
    $SourceUserName `
    $SourcePassword;

$targetConnInfo = InitConnection `
    $TargetServerName `
    $TargetUserName `
    $TargetPassword;

LogMessage -Message "Source and target connection object initialization complete."

استخرج قائمة أسماء الجداول من قاعدة البيانات الهدف

يمكن استخراج قائمة جدول قاعدة البيانات باستخدام مهمة الترحيل ومعلومات الاتصال. سيتم استخراج قائمة الجدول من قاعدة البيانات المصدر وقاعدة البيانات الهدف بحيث يمكن إجراء التعيين والتحقق من الصحة بشكل صحيح.

يأخذ البرنامج النصي التالي أسماء قواعد البيانات المصدر والهدف ثم يستخرج قائمة الجدول من قواعد البيانات باستخدام مهمة الترحيل GetUserTablesMySql.

# Run scenario to get the tables from the target database to build
# the migration table mapping
[string] $TargetDatabaseName = "migtargetdb"
[string] $SourceDatabaseName = "migsourcedb"

function RunScenario([object] $MigrationService,
    [object] $MigrationProject,
    [string] $ScenarioTaskName,
    [object] $TaskProperties,
    [bool] $WaitForScenario = $true) {
    # Check if the scenario task already exists, if so remove it
    LogMessage -Message "Removing scenario if already exists..." -IsProcessing $true
    Remove-AzDataMigrationTask `
        -ResourceGroupName $MigrationService.ResourceGroupName `
        -ServiceName $MigrationService.Name `
        -ProjectName $MigrationProject.Name `
        -TaskName $ScenarioTaskName `
        -Force;

    # Start the new scenario task using the provided properties
    LogMessage -Message "Initializing scenario..." -IsProcessing $true
    New-AzResource `
        -ApiVersion 2018-03-31-preview `
        -Location $MigrationService.Location `
        -ResourceId "/subscriptions/$($global:currentSubscriptionId)/resourceGroups/$($MigrationService.ResourceGroupName)/providers/Microsoft.DataMigration/services/$($MigrationService.Name)/projects/$($MigrationProject.Name)/tasks/$($ScenarioTaskName)" `
        -Properties $TaskProperties `
        -Force | Out-Null;

    LogMessage -Message "Waiting for $ScenarioTaskName scenario to complete..." -IsProcessing $true
    if ($WaitForScenario) {
        $progressCounter = 0;
        do {
            if ($null -ne $scenarioTask) {
                Start-Sleep 10;
            }

            # Get calls can time out and will return a cancellation exception in that case
            $scenarioTask = Get-AzDataMigrationTask `
                -ResourceGroupName $MigrationService.ResourceGroupName `
                -ServiceName $MigrationService.Name `
                -ProjectName $MigrationProject.Name `
                -TaskName $ScenarioTaskName `
                -Expand `
                -ErrorAction Ignore;

            Write-Progress -Activity "Scenario Run $ScenarioTaskName  (Marquee Progress Bar)" `
                -Status $scenarioTask.ProjectTask.Properties.State `
                -PercentComplete $progressCounter

            $progressCounter += 10;
            if ($progressCounter -gt 100) { $progressCounter = 10 }
        }
        while (($null -eq $scenarioTask) -or ($scenarioTask.ProjectTask.Properties.State -eq "Running") -or ($scenarioTask.ProjectTask.Properties.State -eq "Queued"))
    }
    Write-Progress -Activity "Scenario Run $ScenarioTaskName" `
        -Status $scenarioTask.ProjectTask.Properties.State `
        -Completed

    # Now get it using REST APIs so we can expand the output
    LogMessage -Message "Getting expanded task results ..." -IsProcessing $true
    $psToken = (Get-AzAccessToken -ResourceUrl https://management.azure.com).Token;
    $token = ConvertTo-SecureString -String $psToken -AsPlainText -Force;
    $taskResource = Invoke-RestMethod `
        -Method GET `
        -Uri "https://management.azure.com$($scenarioTask.ProjectTask.Id)?api-version=2018-03-31-preview&`$expand=output" `
        -ContentType "application/json" `
        -Authentication Bearer `
        -Token $token;

    $taskResource.properties;
}

# create the get table task properties by initializing the connection and
# database name
$getTablesTaskProperties = @{
    "input"    = @{
        "connectionInfo"    = $null;
        "selectedDatabases" = $null;
    };
    "taskType" = "GetUserTablesMySql";
};

LogMessage -Message "Running scenario to get the list of tables from the target database..." -IsProcessing $true
$getTablesTaskProperties.input.connectionInfo = $targetConnInfo;
$getTablesTaskProperties.input.selectedDatabases = @($TargetDatabaseName);
# Create a name for the task
$getTableTaskName = "$($TargetDatabaseName)GetUserTables"
# Get the list of tables from the source
$getTargetTablesTask = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $getTableTaskName `
    -TaskProperties $getTablesTaskProperties;

if (-not ($getTargetTablesTask)) { throw "ERROR: Could not get target database $TargetDatabaseName table information." }
LogMessage -Message "List of tables from the target database acquired."

LogMessage -Message "Running scenario to get the list of tables from the source database..." -IsProcessing $true
$getTablesTaskProperties.input.connectionInfo = $sourceConnInfo;
$getTablesTaskProperties.input.selectedDatabases = @($SourceDatabaseName);
# Create a name for the task
$getTableTaskName = "$($SourceDatabaseName)GetUserTables"
# Get the list of tables from the source
$getSourceTablesTask = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $getTableTaskName `
    -TaskProperties $getTablesTaskProperties;

if (-not ($getSourceTablesTask)) { throw "ERROR: Could not get source database $SourceDatabaseName table information." }
LogMessage -Message "List of tables from the source database acquired."

بناء مخطط الجدول على أساس تكوين المستخدم

كجزء من تكوين مهمة الترحيل، ستقوم بإنشاء تعيين بين جداول المصدر والهدف. يتم التعيين على مستوى اسم الجدول ولكن الافتراض هو أن بنية الجدول (عدد الأعمدة وأسماء الأعمدة وأنواع البيانات وما إلى ذلك) للجداول المعينة هي نفسها تمامًا.

يقوم البرنامج النصي التالي بإنشاء تعيين بناءً على قائمة الهدف وجدول المصدر المستخرجة في الخطوة 7. بالنسبة للتحميل الجزئي للبيانات، يمكن للمستخدم توفير قائمة بالجدول لتصفية الجداول. إذا لم يتم توفير مدخلات المستخدم، فسيتم تعيين جميع الجداول المستهدفة. يتحقق البرنامج النصي أيضًا من وجود جدول يحمل نفس الاسم في المصدر أم لا. إذا لم يكن اسم الجدول موجودًا في المصدر، فسيتم تجاهل الجدول الهدف للترحيل.

# Create the source to target table map
# Optional table settings
# DEFAULT: $IncludeTables = $null => include all tables for migration
# DEFAULT: $ExcludeTables = $null => exclude no tables from migration
# Exclude list has higher priority than include list
# Array of qualified source table names which should be migrated
[string[]] $IncludeTables = @("migsourcedb.coupons", "migsourcedb.daily_cash_sheets");
[string[]] $ExcludeTables = $null;

LogMessage -Message "Creating the table map based on the user input and database table information ..." `
    -IsProcessing $true

$targetTables = $getTargetTablesTask.Output.DatabasesToTables."$TargetDatabaseName";
$sourceTables = $getSourceTablesTask.Output.DatabasesToTables."$SourceDatabaseName";
$tableMap = New-Object 'system.collections.generic.dictionary[string,string]';

$schemaPrefixLength = $($SourceDatabaseName + ".").Length;
$tableMappingError = $false
foreach ($srcTable in $sourceTables) {
    # Removing the database name prefix from the table name so that comparison
    # can be done in cases where database name given are different
    $tableName = $srcTable.Name.Substring($schemaPrefixLength, `
            $srcTable.Name.Length - $schemaPrefixLength)

    # In case the table is part of exclusion list then ignore the table
    if ($null -ne $ExcludeTables -and $ExcludeTables -contains $srcTable.Name) {
        continue;
    }

    # Either the include list is null or the table is part of the include list then add it in the mapping
    if ($null -eq $IncludeTables -or $IncludeTables -contains $srcTable.Name) {
        # Check if the table exists in the target. If not then log TABLE MAPPING ERROR
        if (-not ($targetTables | Where-Object { $_.name -ieq "$($TargetDatabaseName).$tableName" })) {
            $tableMappingError = $true
            Write-Host "TABLE MAPPING ERROR: $($targetTables.name) does not exists in target." -ForegroundColor Red
            continue;
        }

        $tableMap.Add("$($SourceDatabaseName).$tableName", "$($TargetDatabaseName).$tableName");
    }
}

# In case of any table mapping errors identified, throw an error and stop the process
if ($tableMappingError) { throw "ERROR: One or more table mapping errors were identified. Please see previous messages." }
# In case no tables are in the mapping then throw error
if ($tableMap.Count -le 0) { throw "ERROR: Could not create table mapping." }
LogMessage -Message "Migration table mapping created for $($tableMap.Count) tables."

إنشاء وتكوين مدخلات مهمة الترحيل

بعد بناء مخطط الجدول، ستقوم بإنشاء مدخلات لمهمة الترحيل من النوع Migrate.MySql.AzureDbForMySql وتكوين الخصائص.

يقوم البرنامج النصي التالي بإنشاء مهمة الترحيل وتعيين الاتصالات وأسماء قواعد البيانات وتخطيط الجدول.

# Create and configure the migration scenario based on the connections
# and the table mapping
$offlineMigTaskProperties = @{
    "input"    = @{
        "sourceConnectionInfo"  = $null;
        "targetConnectionInfo"  = $null;
        "selectedDatabases"     = $null;
        "optionalAgentSettings" = @{
            "EnableCacheBatchesInMemory"         = $true;
            "DisableIncrementalRowStatusUpdates" = $true;
        };
        "startedOn"             = $null;
    };
    "taskType" = "Migrate.MySql.AzureDbForMySql";
};
$offlineSelectedDatabase = @{
    "name"               = $null;
    "targetDatabaseName" = $null;
    "tableMap"           = $null;
};

LogMessage -Message "Preparing migration scenario configuration ..." -IsProcessing $true

# Select the database to be migrated
$offlineSelectedDatabase.name = $SourceDatabaseName;
$offlineSelectedDatabase.tableMap = New-Object PSObject -Property $tableMap;
$offlineSelectedDatabase.targetDatabaseName = $TargetDatabaseName;

# Set connection info and the database mapping
$offlineMigTaskProperties.input.sourceConnectionInfo = $sourceConnInfo;
$offlineMigTaskProperties.input.targetConnectionInfo = $targetConnInfo;
$offlineMigTaskProperties.input.selectedDatabases = @($offlineSelectedDatabase);
$offlineMigTaskProperties.input.startedOn = [System.DateTimeOffset]::UtcNow.ToString("O");

تكوين معلمات ضبط الأداء

كجزء من وحدة PowerShell، هناك عدد قليل من المعلمات الاختيارية المتاحة، والتي يمكن ضبطها بناءً على البيئة. يمكن استخدام هذه المعلمات لتحسين أداء مهمة الترحيل. كل هذه المعلمات اختيارية وقيمتها الافتراضية هي NULL.

ملاحظة

أظهرت تكوينات الأداء التالية زيادة الإنتاجية أثناء الترحيل على Premium SKU.

  • WriteDataRangeBatchTaskCount = 12
  • تحديثات تقدم التأخير في فترة التخزين = 30 ثانية
  • ThrottleQueryTableDataRangeTaskAtBatchCount = 36

يأخذ البرنامج النصي التالي قيم المستخدم للمعلمات ويعين المعلمات في خصائص مهمة الترحيل.

# Setting optional parameters from fine tuning the data transfer rate during migration
# DEFAULT values for all the configurations is $null
LogMessage -Message "Adding optional migration performance tuning configuration ..." -IsProcessing $true
# Partitioning settings
# Optional setting that configures the maximum number of parallel reads on tables located on the source database.
[object] $DesiredRangesCount = 4
# Optional setting that configures that size of the largest batch that will be committed to the target server.
[object] $MaxBatchSizeKb = 4096
# Optional setting that configures the minimum number of rows in each batch written to the target.
[object] $MinBatchRows = $null
# Task count settings
# Optional setting that configures the number of databases that will be prepared for migration in parallel.
[object] $PrepareDatabaseForBulkImportTaskCount = $null
# Optional setting that configures the number of tables that will be prepared for migration in parallel.
[object] $PrepareTableForBulkImportTaskCount = $null
# Optional setting that configures the number of threads available to read ranges on the source.
[object] $QueryTableDataRangeTaskCount = 8
# Optional setting that configures the number of threads available to write batches to the target.
[object] $WriteDataRangeBatchTaskCount = 12
# Batch cache settings
# Optional setting that configures how much memory will be used to cache batches in memory before reads on the source are throttled.
[object] $MaxBatchCacheSizeMb = $null
# Optional setting that configures the amount of available memory at which point reads on the source will be throttled.
[object] $ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb = $null
# Optional setting that configures the number of batches cached in memory that will trigger read throttling on the source.
[object] $ThrottleQueryTableDataRangeTaskAtBatchCount = 36
# Performance settings
# Optional setting that configures the delay between updates of result objects in Azure Table Storage.
[object] $DelayProgressUpdatesInStorageInterval = "00:00:30"

function AddOptionalSetting($optionalAgentSettings, $settingName, $settingValue) {
    # If no value specified for the setting, don't bother adding it to the input
    if ($null -eq $settingValue) {
        return;
    }

    # Add a new property to the JSON object to capture the setting which will be customized
    $optionalAgentSettings | add-member -MemberType NoteProperty -Name $settingName -Value $settingValue
}

# Set any optional settings in the input based on parameters to this cmdlet
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "DesiredRangesCount" $DesiredRangesCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MaxBatchSizeKb" $MaxBatchSizeKb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MinBatchRows" $MinBatchRows;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "PrepareDatabaseForBulkImportTaskCount" $PrepareDatabaseForBulkImportTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "PrepareTableForBulkImportTaskCount" $PrepareTableForBulkImportTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "QueryTableDataRangeTaskCount" $QueryTableDataRangeTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "WriteDataRangeBatchTaskCount" $WriteDataRangeBatchTaskCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "MaxBatchCacheSizeMb" $MaxBatchCacheSizeMb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb" $ThrottleQueryTableDataRangeTaskAtAvailableMemoryMb;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "ThrottleQueryTableDataRangeTaskAtBatchCount" $ThrottleQueryTableDataRangeTaskAtBatchCount;
AddOptionalSetting $offlineMigTaskProperties.input.optionalAgentSettings "DelayProgressUpdatesInStorageInterval" $DelayProgressUpdatesInStorageInterval;

إنشاء مهمة الترحيل وتشغيلها

بعد تكوين مدخلات المهمة، سيتم الآن إنشاء المهمة وتنفيذها على الوكيل. يقوم البرنامج النصي بتشغيل تنفيذ المهمة وانتظر اكتمال الترحيل.

يستدعي البرنامج النصي التالي مهمة الترحيل المكونة وينتظر اكتمالها.

# Running the migration scenario
[string] $TaskName = "mysqlofflinemigrate"

LogMessage -Message "Running data migration scenario ..." -IsProcessing $true
$summary = @{
    "SourceServer"   = $SourceServerName;
    "SourceDatabase" = $SourceDatabaseName;
    "TargetServer"   = $TargetServerName;
    "TargetDatabase" = $TargetDatabaseName;
    "TableCount"     = $tableMap.Count;
    "StartedOn"      = $offlineMigTaskProperties.input.startedOn;
}

Write-Host "Job Summary:" -ForegroundColor Yellow
Write-Host $(ConvertTo-Json $summary) -ForegroundColor Yellow

$migrationResult = RunScenario -MigrationService $dmsService `
    -MigrationProject $dmsProject `
    -ScenarioTaskName $TaskName `
    -TaskProperties $offlineMigTaskProperties

LogMessage -Message "Migration completed with status - $($migrationResult.state)"
#Checking for any errors or warnings captured by the task during migration
$dbLevelResult = $migrationResult.output | Where-Object { $_.resultType -eq "DatabaseLevelOutput" }
$migrationLevelResult = $migrationResult.output | Where-Object { $_.resultType -eq "MigrationLevelOutput" }
if ($dbLevelResult.exceptionsAndWarnings) {
    Write-Host "Following database errors were captured: $($dbLevelResult.exceptionsAndWarnings)" -ForegroundColor Red
}
if ($migrationLevelResult.exceptionsAndWarnings) {
    Write-Host "Following migration errors were captured: $($migrationLevelResult.exceptionsAndWarnings)" -ForegroundColor Red
}
if ($migrationResult.errors.details) {
    Write-Host "Following task level migration errors were captured: $($migrationResult.errors.details)" -ForegroundColor Red
}

حذف خدمة ترحيل قاعدة البيانات

يمكن استخدام نفس خدمة ترحيل قاعدة البيانات لعمليات الترحيل المتعددة بحيث يمكن إعادة استخدام المثيل الذي تم إنشاؤه بمجرد إنشائه. إذا كنت لن تستمر في استخدام خدمة ترحيل قاعدة البيانات، فيمكنك حذف الخدمة باستخدام الأمر Remove-AzDataMigrationService.

يحذف البرنامج النصي التالي مثيل Azure Database Migration Service والمشاريع المرتبطة به.

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

الخطوات التالية