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 Sie Datenbankbenutzer, die der benutzerseitig zugewiesenen verwalteten Identität (UMI) zugeordnet sind, um sich bei Zielservern/Datenbanken zu authentifizieren.
- Dabei wird die Verwendung einer UMI mit Microsoft Entra-Authentifizierung (früher Azure Active Directory) als Methode empfohlen. PowerShell-Cmdlets verfügen jetzt über neue Argumente zur Unterstützung der Microsoft Entra-Authentifizierung mit einer UMI.
- Dies ist die empfohlene Authentifizierungsmethode.
- Verwenden Sie der Datenbank zugeordnete Benutzer, denen datenbankbezogenen Anmeldeinformationen in jeder Datenbank zugeordnet sind.
- Zuvor waren datenbankbezogene Anmeldeinformationen die einzige Option für den Agent für elastische Aufträge, sich bei Zielen zu authentifizieren.
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) namensjob-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