Powershell meets SQL Server – Backup einer Remote Datenbank

Auf dem SQLSaturday #525 in St. Augustin hatte ich bereits das Vergnügen Andre Kamann zu lauschen, was er alles mit Powershell und dem SQL Server anstellt, meinen zweiten Kontakt zu Andre hatte ich jetzt beim SQLGrillen in Lingen, bei dem er uns die wesentliche Vereinfachung eines Rollouts des Ola Hallengren Skriptes näher brachte. Irgendwie hat mich diese “Vereinfachung” inspiriert… ich bin eigentlich auch eher ein “fauler Hund” und versuche mir mit Tools, Skripten  oder eigenen unterstützenden Webseiten das DBA Leben zu erleichtern. Heute kam dann ein Ticket zu mir, bei dem es um ein einfaches Backup einer Datenbank ging, der Kunde hat Probleme mit seiner Applikation und möchte nun eine Kopie der Datenbank an den Software-Hersteller schicken. Solche Aufgaben haben wir immer wieder, daher dachte ich heute morgen an Andre und seine Powershell-Skripte.
Viele werden jetzt sagen, so ein Backup ist doch recht einfach => entweder auf den Server per RDP oder von seiner Workstation mit dem SQL Server Management Studio verbinden, dann die Datenbank auswählen und mit der rechten Maus “Tasks => Backup => …” Klar das geht, ABER da wir hier meistens über Citrix Steppingsstones oder Admingates in die Kundennetze müssen, erleichtert es uns die Arbeit schon um einiges, wenn wir den einen oder anderen Hop reduzieren können.

Mein Powershell-Template

Da dies meine ersten Schritte mit Powershell-Skripten sind, musste ich mich erst damit auseinandersetzen, wie man am besten ein solches Powershell Skript strukturell aufbaut. Hierzu habe ich auf diesen Powershell Blogs gelesen und keinen “Standard” ausfindig machen können, aber überall konnte ich mir ein wenig abschauen und somit einen “ersten Wurf” eines Powershell Skript Templates erstellen. Natürlich muss sich dieser noch in der täglichen Arbeit bewähren und eventuell angepasst werden, aber erst einmal kann ich (denke ich zumindest) damit arbeiten.

Angefangen habe ich natürlich mit einem Header

# #############################################################################
# DBA - SCRIPT - POWERSHELL
# NAME: template.ps1
# 
# AUTHOR: Björn Peters, SQL-aus-Hamburg.de
# DATE: 2016/08/24
# EMAIL: info@sql-aus-hamburg.de
# 
# COMMENT: This script will....
#
# VERSION HISTORY
# 1.0 2016.08.24 Initial Version.
# 
#
# OPEN POINTS TO ADD
# -Add a Function to ...
# -Fix the...
# 
# #############################################################################

Aus dem Tagesgeschäft weiß ich bzw habe ich die Erkenntnis gezogen, dass es für den DBA/Ausführenden am einfachsten ist, wenn die ggfs manuell zu konfigurierenden Parameter (wenn sie nicht übergeben werden) ganz oben stehen sollten, damit man sie möglichst schnell findet und einfach editieren kann. Also kommt direkt in meinem Powershell Skript Template nach dem Header ein Abschnitt zur Konfiguration des Skriptes.

# --- CONFIG ---#
# Script Path/Directories
$ScriptPath = (Split-Path ((Get-Variable MyInvocation).Value).MyCommand.Path)
$ScriptPluginPath = $ScriptPath + "\plugin\"
$ScriptToolsPath = $ScriptPath + "\tools\"
$ScriptOutputPath = $ScriptPath + "\Output\"
# Date Format
$DateFormat = Get-Date -Format "ddMMyyyy_HHmmss"
# -- END CONFIG ---#

Jetzt kommen wir zu einem der wichtigsten, aber am meisten vernachlässigten Abschnitten eines solchen Powershell Skriptes… der Hilfe.
Bei meinen Recherchen bin ich immer wieder über den Widerspruch gestolpert, dass man auf der einen Seite möglichst sein Skript kurz und übersichtlich gestalten soll, auf der anderen Seite aber gut dokumentiert und erläutert. Natürlich kann man aus einem Skript mehrere Versionen machen, eine zum Ausführen und eine zum Weitergeben… aber das führt meist zu Fehlern da man garantiert nicht immer alle Änderungen in beiden Daten ausführt => also bitte gleich richtig machen und einen Hilfe-Abschnitt integrieren und ausführlich beschreiben.

# --- HELP ---#
<#
.SYNOPSIS
Cmdlet help is awesome.
 
.DESCRIPTION
This Script does a ton of beautiful things!
 
.PARAMETER
 
.INPUTS
 
.OUTPUTS
 
.EXAMPLE
 
.LINK
http://www.sql-aus-hamburg.de
#>
# --- END HELP ---#

Zu guter letzt bleiben nur noch die Abschnitte für die einzelnen Funktionen und das eigentliche Powershell Skript. Früher (zu meinen VB / VBA Zeiten) hatte ich gelernt, dass man die Funktionen immer nach unten schreibt und den eigentlichen Programmcode nach oben. Aber dies scheint (zumindest für Powershell) mittlerweile überholt zu sein, also kommen die Funktionsaufrufe, die eigentliche Logik des Skriptes nach unten.

# --- FUNCTIONS ---#
Param(
 
)
 
BEGIN {
 
}
 
PROCESS {
 
}
 
END {
 
}
# --- END FUNCTIONS ---#
 
# --- SCRIPT ---#

Quellen und großen Dank an :
http://www.lazywinadmin.com/2012/03/powershell-my-script-template.html
Bei Francois habe ich die meisten Dinge (nachdem ich sie auch anderweitig unter “Best Practices” für Powershell Skripte gelesen hatte) in einem Template gefunden und für mich am besten geeignet befunden. Also habe ich sein Template nahezu 1:1 übernommen.

Mein erstes Powershell Skript

Nun zum eigentlichen SQL Server Backup Skript, welches ich mit Powershell umsetzen wollte.
Also ich wollte mit “Bordmitteln” von einer zentralen Maschine ein Backup auf einem Remote SQL Server erstellen, welches ich dann “einfach” für den Kunden oder Drittdienstleister kopieren und bereitstellen konnte. Was liefert also die SQL Server Installation von Haus aus für Möglichkeiten? Natürlich die SQL Server Management Objects (SMO), welche im Rahmen der Management Tools Installation mitinstalliert werden .

Welche Parameter möchte ich denn angeben bzw übergeben, damit mein Backup erfolgreich läuft…

  • Servername
  • Instanzname
  • Datenbankname
  • SQL-Login => Username/Passwort

Nach einigem Nachdenken kamen noch zwei weitere Parameter dazu… => CopyOnly (True/False) und OpenInExplorer (True/False)

Param(
          [Parameter(Mandatory=$true)][string]$ServerName,
          [string]$InstanceName,
          [Parameter(Mandatory=$true)][string]$DatabaseName,
          [string]$SQLUserName,
          [string]$SQLPwd,
          [switch]$CopyOnly = $True,
          [switch]$OpenInExplorer = $False
)

Also BEGIN der Funktion

Erst einmal alle Parameter überpüfen, zusammensetzen und ggfs umsetzen, so dass sie im Skript bzw T-SQL Befehl verwendet werden können.
Vielleicht kann man das optimaler/sicherer gestalten (Anmerkungen/Tips hierzu bitte über die Kommentarfunktion), aber ich wollte ja einen schnellen Erfolg. Zu Beginn der Funktion prüfe ich also, ob es sich um eine Named-Instance oder Default-Instance handelt, wie der User sich anmelden möchte => Windows Authentifizierung oder SQL Login, on das Backup als Copy-Only-Backup erstellt werden soll und natürlich den Zielort des Backups (Default Backup Directory).

BEGIN {
	"Starting Backup on $($ServerName)"
 
        [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") | out-null
        [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.ConnectionInfo") | out-null
 
        $CommonParameters = ''
 
        if ($InstanceName) {
	    $SQLServer = $ServerName + "\" + $InstanceName
        } else {
            $SQLServer = $ServerName
        }
 
        $SQLSvr = New-Object 'Microsoft.SqlServer.Management.SMO.Server' $SQLServer
        if ($SQLUserName -and $SQLPwd) {
            $SQLSvr.ConnectionContext.LoginSecure=$false;
            $SQLSvr.ConnectionContext.Login=$SQLUserName
            $SQLSvr.ConnectionContext.Password=$SQLPwd
        }
 
	$BackupDir = $SQLSvr.Settings.BackupDirectory "BackupName - $($BackupDir)\$($DatabaseName)_db_$($DateFormat).bak"
 
        if ($CopyOnly -eq $True) { $CommonParameters += " -CopyOnly" }
 
}

Nun kommt der PROCESS

Wie der Name schon sagt, hier geschieht der eigentliche Prozess, also die eigentlich Hauparbeit… Im Falle eines Backup-Skriptes werden hier die Backup Befehle ausgeführt. Da dies mein Einstieg in die Powershell Programmierung ist, es gibt bestimmt Wege dies anders bzw optimaler zu gestalten, aber für mich funktionierte das erst einmal ganz gut so. Wenn also der String $CommonParameters leer oder Null ist wird der einfache Backup Befehl ausgeführt ansonsten werden die WITH-Parameter an den Backup Befehl angehängt. Ansonsten passiert in diesem PROCESS Schritt nicht viel 😉

PROCESS {
        IF([string]::IsNullOrWhiteSpace($CommonParameters)) {
            Backup-SqlDatabase -InputObject $SqlServer -Database $DatabaseName -BackupFile "$($BackupDir)\$($DatabaseName)_db_$($DateFormat).bak"
        } else {
		    Backup-SqlDatabase -InputObject $SqlServer -Database $DatabaseName -BackupFile "$($BackupDir)\$($DatabaseName)_db_$($DateFormat).bak" $CommonParameters
        }
	}

Alles hat ein ENDe

Eigentlich wäre hier nun alles zu Ende, wir haben ein Backup auf einem Remote SQL Server in das Default Backup Verzeichnis geschrieben… hier könnten wir es abholen und dem Anforder zur Verfügung stellen. Aber ich bin ein wenig faul… also was liegt näher als den letzten Schritt noch etwas zu vereinfachen.
Also habe ich in den END Abschnitt einfach einen Explorer Aufruf mit dem Zielpfad (Default Backup Verzeichnis) hinzugefügt, so muss ich nicht erst lange suchen und hin und her klicken, sondern der Explorer öffnet sich direkt mit dem Zielpfad und ich brauche die Datei nur noch weg zu kopieren. 😉

END {
        "Finished Backup on $($ServerName)"
        if ($OpenInExplorer -eq $True) { 
            $NewBackupDir = "\\$($ServerName)\"
            $NewBackupDir += $BackupDir.Replace(':\', '$\')
            Invoke-Item $NewBackupDir 
        }
	}
}
# --- END FUNCTIONS ---#

Zum Abschluss im Skript muss natürlich noch der ganze Ablauf einmal gestartet werden, also rufe ich als “letzte” Zeile des Skriptes schnell die Funktion auf… FERTIG.

Vielen Dank nochmal an Andre für die Inspiration.

Björn arbeitet in Hamburg als Datenbank-Administrator und Head of Competence für MS SQL und mySQL. Er nimmt regelmäßig an den PASS Regionalgruppen Treffen in Hamburg, den Veranstaltungen der PASS wie SQLSaturday und SQLGrillen teil und er organisiert in Hamburg das Azure Meetup. Er interessiert sich neben den Themen rund um den SQL Server, Powershell und Azure für Science-Fiction, Snowboarden, Backen 😉 und Radfahren.

SQL Server 2016 – Backup to URL mit dem Ola Hallengren Skript

In meinem letzten Beitrag zum Thema Backup to Azure habe ich die Möglichkeiten SQL Server Backups in die Azure Cloud zu erstellen angefangen zu erläutern, hierzu möchte ich kurz einen Nachtrag bringen. Viele von euch kennen und nutzen die Backup Skripte von Ola Hallengren, auch diese bieten die Möglichkeiten eines “Backup to URL”. Hierbei gibt es auch etwas zu beachten, ich habe hier meine Tests damit ebenfalls dokumentiert.

Backup to URL mit Ola Hallengren

Wenn man sich un ganz unbedarft des Sache annimmt und – so wie ich – seine ersten Tests mit dem Azure Blob Storage und den Backup to URL macht, dann wird man leider schnell an einen Punkt kommen, wo man doch ein wenig recherchieren und nachdenken muss.  😉

Aber der Reihe nach, ich hatte einen Credential gemäß dem Powershell-Skript angelegt:

CREATE CREDENTIAL [https://backupdemostorage.blob.core.windows.net/backupdemocontainer] WITH IDENTITY='Shared Access Signature', SECRET='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Danach konnte ich einwandfrei meine Backups in den Azure Blog Storage erstellen und diese dort auch auffinden.
Files im Azure Blob Storage

Wie man aus der Dokumentation bzw Beispielen von Ola Hallengrens Backup Skripten entnehmen kann, benötigen wir zur Ausführung des OH-Backups die URL und ein Credential.
Ok, beides habe ich (siehe oben)… also eingefügt und ausgeführt…

EXECUTE dbo.DatabaseBackup
@DATABASES = 'USER_DATABASES',
@URL = 'https://backupdemostorage.blob.core.windows.net/backupdemocontainer',
@Credential = 'https://backupdemostorage.blob.core.windows.net/backupdemocontainer',
@BackupType = 'FULL',
@Compress = 'Y',
@Verify = 'Y'

Sieht zwar lustig aus, ist aber anscheinend so, wenn ich den Output aus dem Powershell-Skript verwende => URL und Credential sind identisch. Die Ausführung des obigen Backups ergibt aber leider einen Fehler 🙁

Backup to URL - Ola Hallengren NOK

Anscheinend setzt Ola Hallengren die Werte anders in den Backup Befehl ein, so dass es hier zu einem Fehler kommt. Und in der Tat, nach einigem Suchen und Lesen, bin ich dem Problem näher gekommen. Der Backup Befehl des SQL Servers kennt eine Option “Credential”, welche durch das Skript gefüllt wird.

CREDENTIAL
Used only when creating a backup to the Windows Azure Blob storage service.

Die Erläuterungen hierzu sind aber auch nicht wirklich großzügig gefüllt… aber man findet in der der MSDN unter Best Practices zum Thema “Backup to URL” weitere Hinweise. So gibt es einen Unterschied in der Anlage der Credentials bzw der Rechte-Vergabe, die mit den “Shared Access Signatures” (siehe Powershell Output) wesentlich umfangreicher bzw detaillierter möglich sind. Also muss man sich vor Anlage bzw Einrichtung einer Backup-to-URL Sicherung Gedanken machen, wie man welche Datenbanken sichern möchte bzw wohin mit welchen Rechten bzw Credentials. Microsoft empfiehlt die Credentials für ein Backup-to-URL mit folgendem Statement anzulegen.

IF NOT EXISTS  
(SELECT * FROM sys.credentials   
WHERE credential_identity = 'mycredential')  
CREATE CREDENTIAL <credential name> WITH IDENTITY = 'mystorageaccount'  
,SECRET = '<storage access key> ;

Wenn man nun diese zusätzlichen Credentials angelegt hat und im Backup-Statement hinterlegt hat, dann funktioniert auch das Ola Hallengren Backup-Skript in Richtung Azure Storage Blob.
Backup to URL Ola Hallengren

Björn arbeitet in Hamburg als Datenbank-Administrator und Head of Competence für MS SQL und mySQL. Er nimmt regelmäßig an den PASS Regionalgruppen Treffen in Hamburg, den Veranstaltungen der PASS wie SQLSaturday und SQLGrillen teil und er organisiert in Hamburg das Azure Meetup. Er interessiert sich neben den Themen rund um den SQL Server, Powershell und Azure für Science-Fiction, Snowboarden, Backen 😉 und Radfahren.

SQL Server 2016 – Backup to Azure Cloud

In Vorbereitung auf kommende Aktivitäten möchte ich nun eine Reihe von Blogbeiträgen zum Thema SQL Server 2016 und Azure schreiben. Welche Möglichkeiten bietet der neue SQL Server 2016 in Verbindung mit der Azure Cloud und wie realisiert man diese. Mir persönlich nützt diese Art von Ausprobieren, Dokumentieren und Schreiben sehr, mal abgesehen von der Anhäufung neuen Wissens und vielleicht kann ich auf diese Weise dem einen oder anderen auch noch behilflich sein.

In meinem ersten Beitrag geht es um ein relativ einfaches aber sehr wichtiges Thema – Backups mit dem SQL Server 2016 in Richtung Azure Cloud. Es soll aber nicht um das Thema Backup allgemein gehen, also warum Backups so wichtig sind und wie man diese Backups erstellt. Viel mehr möchte ich die verschiedenen Wege eines SQL Server Backup in die Azure Cloud zu machen erläutern und dies ggf unter zu Hilfenahme von Powershell.

Einen wichtigen Einwand möchte ich nur kurz grundsätzlich machen, da man manchmal vielleicht beim Erstellen einer Solution nicht unbedingt daran denkt…  Also funktionierende Backups sind absolut notwendig und sehr wichtig, es gibt mehrere Möglichkeiten diese Backups sicher zu erstellen und im Notfall auch schnell “griffbereit” zu haben. Normalerweise ist die schnellste und einfachste Lösung ein lokales “Backup-to-Disc”, was ist aber wenn diese Backup-Platte einmal kaputt geht? Optimaler (bzw Ausfallsicherer) ist das “Backup-to-Share” oder besser bekannt als Backup-to-NetworkDevice (hierbei sollte das Network-Share natürlich als RAID konfiguriert sein. Aber nicht jede kleine Firma ist in der Lage einen entsprechend großen Fileserver zu unterhalten, damit hier die letzten ~5 Tage des SQL-Servers (zusätzlich?!) abgelegt werden können. Was liegt also näher diese Backups auf einen anderen (“günstigen”) redundanten Speicher abzulegen, genau um diese Möglichkeiten geht es in diesem Blogbeitrag.

Möglichkeiten des SQL Servers in Verbindung mit Azure

Seit dem SQL Server 2012 bietet Microsoft mit “SQL Server Backup to URL” die Möglichkeit, wie gewohnt seine verschiedenen Backups zu erstellen. Allerdings ist hierbei nicht eine lokale Festplatte oder ein Fileserver im eigenen Netz das Ziel sondern eine URL aus der Azure Cloud. Dieses Feature wurde im SQL Server 2016 weiter optimiert. Nun stehen weitere Optionen (BlockBlobs, Shared Access Signatures und Striping) bereit, um schneller und sicherer Backups in die Cloud zu erstellen.

Mit dem SQL Server 2014 führte man dann “SQL Server Managed Backup to Microsoft Azure” ein. Dieses neue Feature ermöglichte dem DB-Admin eine vereinfachte und schnellere Arbeit, denn der SQL Server entscheidet selber wann er ein Backup erstellt. Der DBA muss sich nicht erst Gedanken über die Backup Strategie und die Backup-Skripte machen. Natürlich ermöglichen die Optionen auch einen Eingriff durch den DBA, einfacher geht es aber mit den Bordmitteln des SQL Servers. Für Azure SQL Server wird dieses Feature zur Nutzung empfohlen.

Neu hinzugekommen im SQL Server 2016 ist das Feature “File-Snapshot Backups for Database Files in Azure“. Diese Feature ermöglicht dem SQL Server 2016, welcher in Azure läuft ein sehr, sehr schnelles Backup der Datenfiles zu erstellen und somit auch einen schnellen Restore.

SQL Server Backup und Restore mit Azure Blob Storage

Backup to Azure Blob Storage

Was benötigen wir denn alles für die Einrichtung und Anbindung unseres SQL Servers an einen Azure Blob-Speicher?

Da Powershell seit den SQL Server 2012 und 2014 immer mehr an Bedeutung gewinnt, möchte ich auch hier eine kleine Anleitung dazu beisteuern. Heißt es muss erst einmal das Azure-Plugin für Powershell installiert werden. Eine Anleitung und einen Download-Link findet ihr hier => https://azure.microsoft.com/de-de/documentation/articles/powershell-install-configure/
Außerdem benötigt man natürlich einen Account in der Azure-Cloud (170 Euro Test-Zugang), zum Beispiel im Rahmen der Visual Studio Lizenzierung oder als MPN oder BizTalk-Kunde.

Erstellen einer Zugriffs Policy und einer Shared Access Signature

#
# This script uses the Azure Resource model and creates a new ARM storage account.
# Modify this script to use an existing ARM or classic storage account
# using the instructions in comments within this script
#
# Define global variables for the script
$prefixName = '' # used as the prefix for the name for various objects
$subscriptionName='' # the name of subscription name you will use
$locationName = '<a>' # the data center region you will use
$storageAccountName= $prefixName + 'storage' # the storage account name you will create or use
$containerName= $prefixName + 'container' # the storage container name to which you will attach the SAS policy with its SAS token
$policyName = $prefixName + 'policy' # the name of the SAS policy
 
#
# Using Azure Resource Manager deployment model
# Comment out this entire section and use the classic storage account name to use an existing classic storage account
#
 
# Set a variable for the name of the resource group you will create or use
$resourceGroupName=$prefixName + 'rg'
 
# adds an authenticated Azure account for use in the session
Login-AzureRmAccount
 
# set the tenant, subscription and environment for use in the rest of
Set-AzureRmContext -SubscriptionName $subscriptionName
 
# create a new resource group - comment out this line to use an existing resource group
New-AzureRmResourceGroup -Name $resourceGroupName -Location $locationName
 
# Create a new ARM storage account - comment out this line to use an existing ARM storage account
New-AzureRmStorageAccount -Name $storageAccountName -ResourceGroupName $resourceGroupName -Type Standard_RAGRS -Location $locationName
 
# Get the access keys for the ARM storage account
$accountKeys = Get-AzureRmStorageAccountKey -ResourceGroupName $resourceGroupName -Name $storageAccountName
 
# Create a new storage account context using an ARM storage account
$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys[0].Value
 
#
# Using the Classic deployment model
# Use the following four lines to use an existing classic storage account
#
#Classic storage account name
#Add-AzureAccount
#Select-AzureSubscription -SubscriptionName $subscriptionName #provide an existing classic storage account
#$accountKeys = Get-AzureStorageKey -StorageAccountName $storageAccountName
#$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys.Primary
 
# The remainder of this script works with either the ARM or classic sections of code above
 
# Creates a new container in blob storage
$container = New-AzureStorageContainer -Context $storageContext -Name $containerName
$cbc = $container.CloudBlobContainer
 
# Sets up a Stored Access Policy and a Shared Access Signature for the new container
$permissions = $cbc.GetPermissions();
$policyName = $policyName
$policy = new-object 'Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy'
$policy.SharedAccessStartTime = $(Get-Date).ToUniversalTime().AddMinutes(-5)
$policy.SharedAccessExpiryTime = $(Get-Date).ToUniversalTime().AddYears(10)
$policy.Permissions = "Read,Write,List,Delete"
$permissions.SharedAccessPolicies.Add($policyName, $policy)
$cbc.SetPermissions($permissions);
 
# Gets the Shared Access Signature for the policy
$policy = new-object 'Microsoft.WindowsAzure.Storage.Blob.SharedAccessBlobPolicy'
$sas = $cbc.GetSharedAccessSignature($policy, $policyName)
Write-Host 'Shared Access Signature= '$($sas.Substring(1))''
 
# Outputs the Transact SQL to the clipboard and to the screen to create the credential using the Shared Access Signature
Write-Host 'Credential T-SQL'
$tSql = "CREATE CREDENTIAL [{0}] WITH IDENTITY='Shared Access Signature', SECRET='{1}'" -f $cbc.Uri,$sas.Substring(1)
$tSql | clip
Write-Host $tSql</a>

Quelle: https://msdn.microsoft.com/en-us/library/dn466438.aspx

Um dieses Skript nutzen zu können, brauchen wir erst einmal die folgenden Angaben, um sie ins Skript einfügen zu können.

 

Get-AzureSubscription | Format-Table

Nordeuropa ist die optimale Location für Deutschland, ansonsten

Aber um die Angabe Nordeuropa machen zu können, müssen wir uns erst einmal in unseren Azure-Account einloggen und dann eine Liste der verfügbaren Location ausgeben lassen.

Login-AzureRmAccount
Get-AzureRmLocation | Format-Table Location, DisplayName
 
Location       DisplayName     
--------       -----------     
[...]
southcentralus South Central US
northeurope    North Europe    
westeurope     West Europe     
japanwest      Japan West      
[...]

Diese Werte in das Skript eingebaut und ausgeführt, sollte zu folgender Meldung führen:

Shared Access Signature=  sv=2015-04-05&amp;sr=c&amp;si=backupdemopolicy&amp;sig=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 
Credential T-SQL
CREATE CREDENTIAL [https://backupdemostorage.blob.core.windows.net/backupdemocontainer] WITH IDENTITY='Shared Access Signature', SECRET='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

Dieses TSQL Statement auf dem zusichernden Servern einfach ausführen, mittels

SELECT * FROM sys.credentials

kann man den Erfolg überprüfen, falls man der Meldung im SQL Management Studio nicht traut.

Jetzt sind wir eigentlich so weit, dass wir direkt ein Backup in unseren erstellten Azure Storage erstellen können. Hierzu einfach ein Backup-to-URL ausführen (natürlich die Werte entsprechend ersetzen) :

BACKUP DATABASE AdventureWorks2014 TO URL = 'https://.blob.core.windows.net//AdventureWorks2014_onprem.bak'

Bei meinen Tests war ich ganz angetan von der Geschwindigkeit mit der die Backups dort abgelegt werden. Natürlich ist die Geschwindigkeit zum Beispiel abhängig von der eigenen Netzwerk-Infrastruktur bzw der Anbindung ans Internet. ( bei mir sind es 100MB down/ 50MB up )
Ergebnis: ein ~43MB TransactionLog-Backup brauchte 12,7 Sekunden

BACKUP LOG successfully processed 13569 pages in 12.696 seconds (8.349 MB/sec).

Zum Vergleich habe ich das gleiche TransactionLog-Backup nochmal auf die lokale Platte erstellt:

BACKUP LOG successfully processed 13569 pages in 1.746 seconds (60.652 MB/sec).

Was natürlich wesentlich schneller ist, aber eben auch einen gewissen Unsicherheitsfaktor beinhaltet. In diesem Beitrag sollte es aber erst einmal nur um einen ersten Einblick zum Thema SQL Server Backup und Azure Cloud gehen. Wie man nun diese Möglichkeiten und ihre Vor-und Nachteile mit einander verbindet, dass muss jeder für sich, sein Unternehmen und seine Applikationen selber definieren.

Nachtrag:

In dem Skript von Microsoft zur Erstellung eines BlobStorages hatte sich ein Fehler eingeschlichen…
In Zeile 38 steht aktuell:

$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys.[0].Value

es muss aber

$storageContext = New-AzureStorageContext -StorageAccountName $storageAccountName -StorageAccountKey $accountKeys[0].Value

heißen.

Anhand der “vorgefertigten” und korrigierten 😉  Skripte (Danke Microsoft) habe ich für das Aufsetzen dieses Azure Storage Blobs und ein erstes SQL Server Backup-to-URL kaum mehr als 20 Minuten gebraucht.

So und nun viel Spaß beim Ausprobieren und selber Testen. In meinem nächsten Blog gehe ich auf eine der anderen Backup-Möglichkeiten mit dem SQL Server 2016 und Azure ein.

Björn arbeitet in Hamburg als Datenbank-Administrator und Head of Competence für MS SQL und mySQL. Er nimmt regelmäßig an den PASS Regionalgruppen Treffen in Hamburg, den Veranstaltungen der PASS wie SQLSaturday und SQLGrillen teil und er organisiert in Hamburg das Azure Meetup. Er interessiert sich neben den Themen rund um den SQL Server, Powershell und Azure für Science-Fiction, Snowboarden, Backen 😉 und Radfahren.