Erstellen und Verwalten von elastischen Aufträgen mithilfe von PowerShell

Gilt für:: Azure SQL-Datenbank

Dieser Artikel enthält ein Tutorial und Beispiele für die ersten Schritte bei der Arbeit mit PowerShell an elastischen Auträgen. Mit elastischen Aufträgen können einzelne oder mehrere T-SQL-Skripts (Transact-SQL) für mehrere Datenbanken gleichzeitig ausgeführt werden.

In diesem End-to-End-Tutorial erfahren Sie, wie Sie eine datenbankübergreifende Abfrage ausführen:

  • Erstellen eines Agents für elastischen Auftrags
  • Erstellen von Auftragsanmeldeinformationen, damit Aufträge Skripts für die Ziele ausführen können
  • Definieren der Ziele (Server, Pools für elastische Datenbanken, Datenbanken), für die der Auftrag ausgeführt werden soll
  • Erstellen von datenbankweit gültigen Anmeldeinformationen in den Zieldatenbanken, damit der Agent eine Verbindung herstellen und Aufträge ausführen kann
  • Erstellen eines Auftrags
  • Hinzufügen von Auftragsschritten zu einem Auftrag
  • Starten der Auftragsausführung
  • Überwachen eines Auftrags

Voraussetzungen

Datenbanken für elastische Aufträge verfügen über eine Reihe von PowerShell-Cmdlets.

Diese Cmdlets wurden im November 2023 aktualisiert.

Installieren der neuesten Cmdlets für elastische Aufträge

Wenn Sie kein Azure-Abonnement besitzen, können Sie ein kostenloses Konto erstellen, bevor Sie beginnen.

Falls noch nicht vorhanden, installieren Sie die neuesten Versionen der Az.Sql- und SqlServer-Module. Führen Sie die folgenden Befehle in PowerShell mit Administratorzugriff aus.

# installs the latest PackageManagement and PowerShellGet packages
Find-Package PackageManagement | Install-Package -Force
Find-Package PowerShellGet | Install-Package -Force

# Restart your powershell session with administrative access

# Install and import the Az.Sql module, then confirm
Install-Module -Name Az.Sql
Import-Module Az.Sql
Install-Module -Name SqlServer
Import-Module SqlServer

Ausführliche Informationen finden Sie unter Installieren des SQL Server PowerShell-Moduls.

Erstellen der erforderlichen Ressourcen

Um einen Agent für elastische Aufträge erstellen zu können, benötigen Sie eine Auftragsdatenbank (S1 oder höher).

Das folgende Skript erstellt eine neue Ressourcengruppe, einen neuen Server und eine neue Datenbank, die Sie als Dantenbank für elastische Auträge verwenden können. Das zweite Skript erstellt einen zweiten Server mit zwei leeren Datenbanken, für die Aufträge ausgeführt werden können.

Für elastische Aufträge gelten keine speziellen Benennungsanforderungen. Sie können also beliebige Namenskonventionen verwenden, solange diese die Anforderungen von Azure erfüllen. Wenn Sie bereits eine leere Datenbank erstellt haben, die als Datenbank für elastische Aufträge dienen soll, fahren Sie mit Erstellen des Agents für elastische Aufträge fort.

Das Konfigurieren einer Firewallregel mit New-AzSqlServerFirewallRule ist nicht erforderlich, wenn Sie einen privaten Endpunkt für elastische Aufträge verwenden.

# Sign in to your Azure account
Connect-AzAccount

# The SubscriptionId in which to create these objects
$SubscriptionId = '<your subscription id>'
# Set subscription context, important if you have access to more than one subscription.
Set-AzContext -SubscriptionId $subscriptionId 

# Create a resource group
Write-Output "Creating a resource group..."
$resourceGroupName = Read-Host "Please enter a resource group name"
$location = Read-Host "Please enter an Azure Region, for example westus2"
$rg = New-AzResourceGroup -Name $resourceGroupName -Location $location
$rg

# Create an Azure SQL logical server
Write-Output "Creating a server..."
$agentServerName = Read-Host "Please enter an agent server name"
$agentServerName = $agentServerName + "-" + [guid]::NewGuid()
$adminLogin = Read-Host "Please enter the server admin name"
$adminPassword = Read-Host "Please enter the server admin password"
$adminPasswordSecure = ConvertTo-SecureString -String $AdminPassword -AsPlainText -Force
$adminCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList $adminLogin, $adminPasswordSecure
$parameters = @{
    ResourceGroupName = $resourceGroupName 
    Location = $location
    ServerName = $agentServerName 
    SqlAdministratorCredentials = ($adminCred)    
}
$agentServer = New-AzSqlServer @parameters

# Set server firewall rules to allow all Azure IPs
# Unnecessary if using an elastic jobs private endpoint
Write-Output "Creating a server firewall rule..."
$agentServer | New-AzSqlServerFirewallRule -AllowAllAzureIPs -FirewallRuleName "Allowed IPs"
$agentServer

# Create the job database
Write-Output "Creating a blank database to be used as the Job Database..."
$jobDatabaseName = "JobDatabase"
$parameters = @{
    ResourceGroupName = $resourceGroupName 
    ServerName = $agentServerName 
    DatabaseName = $jobDatabaseName 
    RequestedServiceObjectiveName = "S1"
}
$jobDatabase = New-AzSqlDatabase @parameters
$jobDatabase
# Create a target server and sample databases - uses the same credentials
Write-Output "Creating target server..."
$targetServerName = Read-Host "Please enter a target server name"
$targetServerName = $targetServerName + "-" + [guid]::NewGuid()
$parameters = @{
    ResourceGroupName= $resourceGroupName
    Location= $location 
    ServerName= $targetServerName
    ServerVersion= "12.0"
    SqlAdministratorCredentials= ($adminCred)
}
$targetServer = New-AzSqlServer @parameters

# Set target server firewall rules to allow all Azure IPs
# Unnecessary if using an elastic jobs private endpoint
$targetServer | New-AzSqlServerFirewallRule -AllowAllAzureIPs 

# Set the target firewall to include your desired IP range. 
# Change the following -StartIpAddress and -EndIpAddress values.
$parameters = @{
    StartIpAddress = "0.0.0.0" 
    EndIpAddress = "0.0.0.0"
    FirewallRuleName = "AllowAll"
}
$targetServer | New-AzSqlServerFirewallRule @parameters
$targetServer

# Create two sample databases to execute jobs against
$parameters = @{
    ResourceGroupName = $resourceGroupName 
    ServerName = $targetServerName 
    DatabaseName = "database1"
}
$db1 = New-AzSqlDatabase @parameters
$db1
$parameters = @{
    ResourceGroupName = $resourceGroupName 
    ServerName = $targetServerName 
    DatabaseName = "database2"
}
$db2 = New-AzSqlDatabase @parameters
$db2

Erstellen des Agents für elastische Aufträge

Bei einem Agent für elastische Aufträge handelt es sich um eine Azure-Ressource zum Erstellen, Ausführen und Verwalten von Aufträgen. Der Agent führt Aufträge gemäß einem Zeitplan oder einmalig aus. Alle Datums- und Zeitangaben in elastischen Aufträgen folgen der UTC-Zeitzone.

Für das Cmdlet New-AzSqlElasticJobAgent muss bereits eine Datenbank in Azure SQL-Datenbank vorhanden sein. Daher müssen die Parameter resourceGroupName, serverName und databaseName auf vorhandene Ressourcen verweisen. Ebenso kann Set-AzSqlElasticJobAgent verwendet werden, um den Agent für elastische Aufträge zu ändern.

Verwenden Sie zum Erstellen eines neuen elastischen Auftrags-Agenten mithilfe der Microsoft Entra-Authentifizierung mit einer vom Benutzer zugewiesenen verwalteten Identität die Argumente IdentityType und IdentityID von New-AzSqlElasticJobAgent:

Write-Output "Creating job agent..."
$agentName = Read-Host "Please enter a name for your new elastic job agent"
$parameters = @{
    Name = $agentName 
    IdentityType = "UserAssigned" 
    IdentityID = "/subscriptions/abcd1234-caaf-4ba9-875d-f1234/resourceGroups/contoso-jobDemoRG/providers/Microsoft.ManagedIdentity/userAssignedIdentities/contoso-UMI"
}
$jobAgent = $jobDatabase | New-AzSqlElasticJobAgent @parameters
$jobAgent

Zum Erstellen eines neuen elastischen Auftrags-Agenten mithilfe von Anmeldeinformationen mit Datenbankbereich werden IdentityType und IdentityID nicht bereitgestellt.

Erstellen der Auftragsauthentifizierung

Der Agent für elastische Aufträge muss in der Lage sein, sich bei jedem Zielserver oder jeder Zieldatenbank zu authentifizieren.

Wie unter Authentifizierung eines Aufrags–Agents erstellen beschrieben:

Verwenden der Microsoft Entra-Authentifizierung mit einer UMI für die Authentifizierung auf Ziele

Um die empfohlene Methode der Authentifizierung mit Microsoft Entra (früher Azure Active Directory) für eine benutzerseitig zugewiesene verwaltete Identität (UMI) zu verwenden, führen Sie die folgenden Schritte aus. Der Agent für elastische Aufträge stellt über die Entra-Authentifizierung eine Verbindung mit dem gewünschten logischen Zielserver/-datenbanken(n) bereit.

Beachten Sie, dass zusätzlich zu den Anmelde- und Datenbankbenutzern die GRANT-Befehle im folgenden Skript hinzugefügt werden müssen. Diese Berechtigungen werden für das Skript benötigt, das wir für diesen Beispielauftrag ausgewählt haben. Für Ihre Aufträge sind möglicherweise unterschiedliche Berechtigungen erforderlich. Da im Beispiel eine neue Tabelle in den Zieldatenbanken erstellt wird, benötigt der Datenbankbenutzer in jeder Zieldatenbank die richtigen Berechtigungen, um das Beispiel erfolgreich auszuführen.

Erstellen Sie für den/die einzelnen Zielserver/-datenbank(en) einen enthaltenen Benutzer, der der UMI zugeordnet ist.

  • Wenn der elastische Auftrag logische Server- oder Poolziele hat, müssen Sie den eigenständigen Benutzer, der der UMI zugeordnet ist, in der Datenbank master des logischen Zielservers erstellen.
  • Zum Beispiel, um ein Login für eine eigenständige Datenbank in der master-Datenbank und einen Benutzer in der Benutzerdatenbank zu erstellen, basierend auf der benutzerseitig zugewiesenen verwalteten Identität (UMI) namens job-agent-UMI:
$targetServer = '<target server name>'
$adminLogin = '<username>'
$adminPassword = '<password>'

# For the target logical server, in the master database
# Create the login named [job-agent-UMI] based on the UMI [job-agent-UMI], and a user
$params = @{
  'database' = 'master'
  'serverInstance' =  $targetServer.ServerName + '.database.windows.net'
  'username' = $adminLogin
  'password' = $adminPassword
  'outputSqlErrors' = $true
  'query' = 'CREATE LOGIN [job-agent-UMI] FROM EXTERNAL PROVIDER;'
}
Invoke-SqlCmd @params
$params.query = "CREATE USER [job-agent-UMI] FROM LOGIN [job-agent-UMI]"
Invoke-SqlCmd @params

# For each target database in the target logical server
# Create a database user from the job-agent-UMI login 
$targetDatabases = @( $db1.DatabaseName, $Db2.DatabaseName )
$createJobUserScript =  "CREATE USER [job-agent-UMI] FROM LOGIN [job-agent-UMI]"

# Grant permissions as necessary. For example ALTER and CREATE TABLE:
$grantAlterSchemaScript = "GRANT ALTER ON SCHEMA::dbo TO [job-agent-UMI]" 
$grantCreateScript = "GRANT CREATE TABLE TO [job-agent-UMI]"

$targetDatabases | % {
  $params.database = $_
  $params.query = $createJobUserScript
  Invoke-SqlCmd @params
  $params.query = $grantAlterSchemaScript
  Invoke-SqlCmd @params
  $params.query = $grantCreateScript
  Invoke-SqlCmd @params
}

Verwenden von gezielten Anmeldeinformationen für die Authentifizierung bei Zielen

Auftrags-Agents vverwenden bei der Ausführung die von der Zielgruppe angegebenen Anmeldeinformationen und führen Skripte aus. Diese datenbankweit gültigen Anmeldeinformationen werden auch zur Verbindungsherstellung mit der master-Datenbank verwendet, um alle Datenbanken auf einem Server oder in einem Pool für elastische Datenbanken zu enumerieren, sofern sie der Zielgruppe angehören.

Die datenbankweit gültigen Anmeldeinformationen müssen in der Auftragsdatenbank erstellt werden. Für eine erfolgreiche Auftragsausführung müssen alle Zieldatenbanken über eine Anmeldung mit ausreichenden Berechtigungen verfügen.

Beachten Sie neben den Anmeldeinformationen in der Abbildung auch die hinzugefügten Befehle vom Typ GRANT im folgenden Skript. Diese Berechtigungen werden für das Skript benötigt, das wir für diesen Beispielauftrag ausgewählt haben. Für Ihre Aufträge sind möglicherweise unterschiedliche Berechtigungen erforderlich. Da im Beispiel eine neue Tabelle in den Zieldatenbanken erstellt wird, benötigt der Datenbankbenutzer in jeder Zieldatenbank die richtigen Berechtigungen, um das Beispiel erfolgreich auszuführen.

Das Login/Der Benutzer auf jedem Zielserver/jeder Zieldatenbank muss denselben Namen wie die Identität der datenbankübergreifenden Anmeldeinformationen für den Auftragsbenutzer und dasselbe Passwort wie die datenbankübergreifenden Anmeldeinformationen für den Auftragsbenutzer haben. Während das PowerShell-Skript <strong jobuser password here> verwendet, verwenden Sie dasselbe Kennwort überall.

Im folgenden Beispiel werden datenbankübergreifende Anmeldeinformationen verwendet. Um die erforderlichen Auftragsanmeldeinformationen (in der Auftragsdatenbank) zu erstellen, führen Sie das folgende Skript aus, das die SQL-Authentifizierung für die Verbindung mit dem/den Zielserver(n)/Datenbank(en) verwendet:

# For the target logical server, in the master database
# Create the master user login, master user, and job user login
$targetServer = '<target server name>'
$adminLogin = '<username>'
$adminPassword = '<password>'

$params = @{
  'database' = 'master'
  'serverInstance' =  $targetServer + '.database.windows.net'
  'username' = $adminLogin
  'password' = $adminPassword
  'outputSqlErrors' = $true
  'query' = 'CREATE LOGIN adminuser WITH PASSWORD=''<strong adminuser password here>'''
}
Invoke-SqlCmd @params
$params.query = "CREATE USER adminuser FROM LOGIN adminuser"
Invoke-SqlCmd @params
$params.query = 'CREATE LOGIN jobuser WITH PASSWORD=''<strong jobuser password here>'''
Invoke-SqlCmd @params

# For each target database in the target logical server
# Create the jobuser from jobuser login and check permission for script execution
$targetDatabases = @( $db1.DatabaseName, $Db2.DatabaseName )
$createJobUserScript =  "CREATE USER jobuser FROM LOGIN jobuser"

# Grant permissions as necessary. For example ALTER and CREATE TABLE:
$grantAlterSchemaScript = "GRANT ALTER ON SCHEMA::dbo TO jobuser"
$grantCreateScript = "GRANT CREATE TABLE TO jobuser"

$targetDatabases | % {
  $params.database = $_
  $params.query = $createJobUserScript
  Invoke-SqlCmd @params
  $params.query = $grantAlterSchemaScript
  Invoke-SqlCmd @params
  $params.query = $grantCreateScript
  Invoke-SqlCmd @params
}

# Create job credential in job database for admin user
Write-Output "Creating job credentials..."
$loginPasswordSecure = (ConvertTo-SecureString -String '<strong jobuser password here>' -AsPlainText -Force)
$loginadminuserPasswordSecure = (ConvertTo-SecureString -String '<strong adminuser password here>' -AsPlainText -Force)

$adminCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "adminuser", $loginadminuserPasswordSecure
$adminCred = $jobAgent | New-AzSqlElasticJobCredential -Name "adminuser" -Credential $adminCred

$jobCred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "jobuser", $loginPasswordSecure
$jobCred = $jobAgent | New-AzSqlElasticJobCredential -Name "jobuser" -Credential $jobCred

Definieren von Zielservern und Datenbanken

Eine Zielgruppe definiert mindestens eine Gruppe von Datenbanken, für die ein Auftragsschritt ausgeführt wird.

Mit dem folgenden Codeausschnitt werden zwei Zielgruppen serverGroup und serverGroupExcludingDb2 erstellt: serverGroup ist auf alle Datenbanken ausgerichtet, die zum Zeitpunkt der Ausführung auf dem Server vorhanden sind. serverGroupExcludingDb2 ist ebenfalls auf alle Datenbanken auf dem Server ausgerichtet, schließt allerdings TargetDb2 aus:

Write-Output "Creating test target groups..."
# create ServerGroup target group
$serverGroup = $jobAgent | New-AzSqlElasticJobTargetGroup -Name 'ServerGroup'
$serverGroup | Add-AzSqlElasticJobTarget -ServerName $targetServerName -RefreshCredentialName $adminCred.CredentialName

# create ServerGroup with an exclusion of db2
$serverGroupExcludingDb2 = $jobAgent | New-AzSqlElasticJobTargetGroup -Name 'ServerGroupExcludingDb2'
$serverGroupExcludingDb2 | Add-AzSqlElasticJobTarget -ServerName $targetServerName -RefreshCredentialName $adminCred.CredentialName
$serverGroupExcludingDb2 | Add-AzSqlElasticJobTarget -ServerName $targetServerName -Database $db2.DatabaseName -Exclude

Erstellen eines Auftrags und von Schritten

In diesem Beispiel werden ein Auftrag und zwei Auftragsschritte definiert, die durch den Auftrag ausgeführt werden sollen. Der erste Auftragsschritt (step1) erstellt in jeder Datenbank aus der Zielgruppe Step1Table eine neue Tabelle (ServerGroup). Der zweite Auftragsschritt (step2) erstellt in jeder Datenbank (mit Ausnahme von Step2Table, da die zuvor definierte Zielgruppe diese Datenbank ausschließt) eine neue Tabelle (TargetDb2).

Write-Output "Creating a new job..."
$jobName = "Job1"
$job = $jobAgent | New-AzSqlElasticJob -Name $jobName -RunOnce
$job

Write-Output "Creating job steps..."
$sqlText1 = "IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = object_id('Step1Table')) CREATE TABLE [dbo].[Step1Table]([TestId] [int] NOT NULL);"
$sqlText2 = "IF NOT EXISTS (SELECT * FROM sys.tables WHERE object_id = object_id('Step2Table')) CREATE TABLE [dbo].[Step2Table]([TestId] [int] NOT NULL);"

$job | Add-AzSqlElasticJobStep -Name "step1" -TargetGroupName $serverGroup.TargetGroupName -CredentialName $jobCred.CredentialName -CommandText $sqlText1
$job | Add-AzSqlElasticJobStep -Name "step2" -TargetGroupName $serverGroupExcludingDb2.TargetGroupName -CredentialName $jobCred.CredentialName -CommandText $sqlText2

Ausführung des Auftrags

Verwenden Sie den folgenden Befehl, um den Auftrag sofort zu starten:

Write-Output "Start a new execution of the job..."
$jobExecution = $job | Start-AzSqlElasticJob
$jobExecution

Nach erfolgreichem Abschluss sollten Sie zwei neue Tabellen in TargetDb1 und nur eine neue Tabelle in TargetDb2 sehen.

Sie können auch eine spätere Ausführung des Auftrags planen.

Wichtig

Alle Zeitangaben in elastischen Aufträgen folgen der UTC-Zeitzone.

Führen Sie den folgenden Befehl aus, um die Ausführung eines Auftrags für einen späteren Zeitpunkt zu planen:

# run every hour starting from now
$job | Set-AzSqlElasticJob -IntervalType Hour -IntervalCount 1 -StartTime (Get-Date) -Enable

Überwachen des Auftragsausführungsstatus

Die folgenden Codeausschnitte dienen zum Abrufen von Details zur Auftragsausführung:

# get the latest 10 executions run
$jobAgent | Get-AzSqlElasticJobExecution -Count 10

# get the job step execution details
$jobExecution | Get-AzSqlElasticJobStepExecution

# get the job target execution details
$jobExecution | Get-AzSqlElasticJobTargetExecution -Count 2

In der folgenden Tabelle werden die möglichen Auftragsausführungsstatus aufgeführt:

State BESCHREIBUNG
Erstellt Die Ausführung des Auftrags wurde gerade erstellt und wird noch nicht durchgeführt.
InProgress Der Auftrag wird zurzeit ausgeführt.
WaitingForRetry Die Aktion der Auftragsausführung konnte nicht abgeschlossen werden, und es wird auf einen erneuten Versuch gewartet.
Erfolgreich Der Auftrag wurde erfolgreich ausgeführt.
SucceededWithSkipped Der Auftrag wurde erfolgreich ausgeführt, aber einige seiner untergeordneten Schritte wurden übersprungen.
Fehler Bei der Ausführung des Auftrags sind Fehler aufgetreten und die Anzahl der möglichen Wiederholungsversuche ist ausgeschöpft.
TimedOut Für die Ausführung des Auftrags ist ein Timeout in Kraft getreten.
Canceled Die Ausführung des Auftrags wurde abgebrochen.
Übersprungen Die Auftragsausführung wurde übersprungen, weil eine andere Ausführung des gleichen Auftragsschritts bereits auf dem gleichen Ziel durchgeführt wurde.
WaitingForChildJobExecutions Die Ausführung des Auftrags wartet auf den Abschluss untergeordneter Schritte.

Bereinigen von Ressourcen

Löschen Sie die Ressourcengruppe, um die in diesem Tutorial erstellten Azure-Ressourcen zu löschen.

Tipp

Wenn Sie diese Aufträge weiterverwenden möchten, überspringen Sie die Bereinigung der in diesem Artikel erstellten Ressourcen.

Remove-AzResourceGroup -ResourceGroupName $resourceGroupName

Nächster Schritt