Haikos Blog Blog von Haiko Hertes zu allen Themen rund um Microsoft und Datacenter

27Mrz/190

Azure / PowerShell – Azure SQL Performance Empfehlungen per PowerShell abholen und verteilen

Azure und insbesondere Azure SQL ist klasse - es nimmt einem viele Dinge der täglichen Verwaltung ab, einiges davon sogar automatisch. Klar, das hat seinen Preis, immerhin ist Azure SQL nicht ganz billig, aber wenn man es schon bezahlt, dann kann man auch seine Fähigkeiten nutzen. Eine davon ist, automatisch anhand der Nutzung einer Datenbank Empfehlungen für die Leistungsoptimierung zu geben. Diese kann man sich im UI bzw. dem Azure Portal anschauen. Dazu öffnet man entweder links im Blade den Punkt "Recommondations" unterhalb von "Intelligent Performance" oder den Punkt "Performance" auf der Main-Page bei den Notifications:

Dort sieht man dann einige Empfehlungen aufgeführt (vorausgesetzt, Azure hat etwas gefunden, was wiederum eine regelmäßige Nutzung der Datenbank voraussetzt):

Diese Daten kann man sich auch automatisch abrufen und auf Wunsch dann z.B. an die Entwickler verteilen. Dazu bediene ich mich einfach der PowerShell:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
$ErrorActionPreference = "Stop"
$SubscriptionId = "YOUR_SUBSCRIPTION_ID"
 
function Get-SQLServerRecommendations()
{
    # Define the resource types
    $resourceTypes = ("Microsoft.Sql/servers/databases")
    $advisors = ("CreateIndex", "DropIndex","DbParameterization","SchemaIssue");
    $results = @()
 
    # Loop through all subscriptions
 
    $rgs = Get-AzureRmResourceGroup
 
    # Loop through all resource groups
    foreach($rg in $rgs) {
        $rgname = $rg.ResourceGroupName;
 
        # Loop through all resource types
        foreach($resourceType in $resourceTypes) {
            $resources = Get-AzureRmResource -ResourceGroupName $rgname -ResourceType $resourceType
 
            # Loop through all databases
            # Extract resource groups, servers and databases
            foreach ($resource in $resources) {
                $resourceId = $resource.ResourceId
                if ($resourceId -match ".*RESOURCEGROUPS/(?<content>.*)/PROVIDERS.*") {
                    $ResourceGroupName = $matches['content']
                } else {
                    continue
                }
                if ($resourceId -match ".*SERVERS/(?<content>.*)/DATABASES.*") {
                    $ServerName = $matches['content']
                } else {
                    continue
                }
                if ($resourceId -match ".*/DATABASES/(?<content>.*)") {
                    $DatabaseName = $matches['content']
                } else {
                    continue
                }
 
                # Skip if master
                if ($DatabaseName -eq "master") {
                    continue
                }
 
                # Loop through all Automatic tuning recommendation types
                foreach ($advisor in ($advisors -notmatch "SchemaIssue")) {
                    $recs = Get-AzureRmSqlDatabaseRecommendedAction -ResourceGroupName $ResourceGroupName -ServerName $ServerName  -DatabaseName $DatabaseName -AdvisorName $advisor
                    foreach ($r in $recs) {
                        if ($r.State.CurrentValue -eq "Active") {
                            $object = New-Object -TypeName PSObject
                            $object | Add-Member -Name 'SubscriptionId' -MemberType Noteproperty -Value $subscriptionId
                            $object | Add-Member -Name 'ResourceGroupName' -MemberType Noteproperty -Value $r.ResourceGroupName
                            $object | Add-Member -Name 'ServerName' -MemberType Noteproperty -Value $r.ServerName
                            $object | Add-Member -Name 'DatabaseName' -MemberType Noteproperty -Value $r.DatabaseName
                            $object | Add-Member -Name 'Advisor' -MemberType Noteproperty -Value $advisor
                            $object | Add-Member -Name 'Script' -MemberType Noteproperty -Value $r.ImplementationDetails.Script
                            $results += $object
                        }
                    }
                }
            }
        }
    }
    Return $results
}
 
$AzurePasswordSecure = ConvertTo-SecureString "$($YOUR_AZURE_PASSWORD)" -AsPlainText -Force
$AzureCredentials = New-Object System.Management.Automation.PSCredential ("$YOUR_AZURE_USER", $AzurePasswordSecure)
Connect-AzureRmAccount -Credential $AzureCredentials | Out-Null
Select-AzureRmSubscription -Subscription $SubscriptionId | Out-Null
 
$Recommendations = Get-SQLServerRecommendations
$table = $Recommendations | Sort-Object DatabaseName,Advisor | Format-Table Databasename,Advisor,Script -AutoSize -Wrap
Write-Output $table
 
$head = "<style>
td {background-color:lightgrey;}
table {width:100%;}
th {font-size:14pt;background-color:lightblue;}
</style>
<title>SQL Server performance recommendations</title>"
 
[string]$html = $Recommendations | ConvertTo-Html -Property Databasename,Advisor,Script -Body "<h1>Azure SQL Server automatic tuning recommendations for $stage</h1>Auto-generated by PUT_SOMETHING_HERE<br><br>" -Head $head
 
Send-MailMessage -Body $html -SmtpServer YOUR.SMTPSERVER.COM -From sender@domain.com -To recipient@domain.com -Subject "MS SQL Recommendations - $(Get-Date -Format "yyyy-dd-MM HH:mm:ss")" -BodyAsHtml

Dieses Script wiederum kann man dann z.B. per Jenkins regelmäßig auslösen. Oder alternativ ein Azure Automation Runbook dafür anlegen... Viel Spaß beim Ausprobieren!

Die Mails sehen dann in etwa so aus:

10Jul/152

SCCM 2012 R2: Wie man den Configuration Manager installiert

Ich habe euch ein Video erstellt, in dem ihr sehen könnt wie ihr:

  1. die Voraussetzungen für eine SCCM-Installation (inklusive SQL-Server) schafft und
  2. den System Center Configuration Manager 2012 R2 installiert.

Das Ganze zeige ich am Beispiel einer Single-Server-Lösung für eine Stand-alone Primary Site, lässt sich aber auf viele andere Szenarien übertragen.

 

Viel Spaß mit dem Video!

10Jun/150

SCDPM meldet “Der Schutz kann nicht konfiguriert werden” wenn SQL Server gesichert werden soll

Bei der Version 2012 R2 des System Center Data Protection Managers gibt es ein Problem mit der Sicherung von SQL Servern der Version 2012. Es wird nach Erstellen der Schutzgruppe bzw. beim Versuch der Erstellung eines Replikates die Meldung “Der Schutz kann nicht konfiguriert werden” ausgegeben (Im Englischen: “Unable to configure protection”).

scdpm_sql_00

(Leider hab ich vom Fehler selbst in der Produktiv-Umgebung keinen Screenshot gemacht und ich wollte ihn nicht nochmal nachträglich provozieren – daher ein Shot aus einer englischen Umgebung)

Dieses Problem ist scheinbar bei Microsoft bekannt und auch im TechNet dokumentiert:

https://technet.microsoft.com/de-de/library/dn281948.aspx

Die Lösung ist auch recht einfach, da der Grund ebenso einfach ist: Der Schutz-Agent hat keine SA-Rechte auf der Datenbank, also müssen diese noch vergeben werden!

Dazu startet man auf dem zu sichernden Zielserver einfach das “SQL Server Management Studio”:

scdpm_sql_01

Dort kann man dann in dem Bereich “Sicherheit”, unter “Anmeldungen” das Konto von “NT-AUTORITÄT\SYSTEM” mit einem Rechtklick und der Auswahl von “Eigenschaften” öffnen. Hier muss dann die Rolle “sysadmin” zusätzlich mit ausgewählt werden.

scdpm_sql_03

Danach sollte sich die Sicherung via DPM auch problemlos einrichten und durchführen lassen:

scdpm_sql_04

12Jul/120

SQL-Server auf System Center Configuration Manager 2012 (SCCM) Server startet nach SYSPREP nicht mehr

Auf einem Test-Server für eine System Center Configuration Manager 2012 Umgebung lief auch der dazu notwendige SQL-Server. Da die Hardware einen Defekt aufwies, musste ich das System auf eine neue Hardware umziehen. Problematisch: Alte und neue Hardware waren derart verschieden, dass hier Probleme zu erwarten gewesen wären, wenn ich die Platten einfach nur umgesteckt hätte. Also habe ich vorher einen Sysprep inkl. /generalize laufen lassen. Nach dem Umbau der Festplatten in den neuen Server startete dieser Anstandslos. Das Problem: Die SQL-Server-Dienste starteten nicht!

Problem:

Durch den SYSPREP sind die privaten Schlüssel für die SSL-Kommunikation verloren gegangen, da der alte User-Account ja danach nicht mehr vorhanden war. Dies war u.a. im Logfile "C:\Program Files\Microsoft SQL Server\MSSQL10_50.MSSQLSERVER\MSSQL\Log\ERRORLOG" nachzulesen:

"The server could not load the certificate it needs to initiate an SSL connection. It returned the following error: 0x8009030d [...]"

Lösung:

Im "SQL Server Configuration Manager" die Zuordnung zum alten Zertifikat löschen:

 

 

 

 

 

 

 

 

Nach einem Reboot des Servers generiert dieser ein neues Zertifikat und trägt dieses hier entsprechend ein (Es existieren dann 2 Zertifikate mit gleichem Namen, man kann sie aber u.a. am Ausstellungsdatum unterscheiden).

Dieses neue Zertifikat muss nun noch zu den "Vertrauenswürdigen Stammzertifizierungsstellen" hinzugefügt werden bzw. evtl. den Clients als vertrauenswürdig bekanntgegeben werden. Danach sollte alles wieder funktionieren, im Logfile steht dann:

"A self-generaterd certificate was successfully loaded for encryption. [...]"