SQL Server-Datenbankpflege

Einleitung

Die Pflege von Datenbanken ist eine sehr wichtige administrative Aufgabe. Wird diese vernachlässigt ist die Sicherheit des Betriebes (und somit Ihres Unternehmens) gefährdet und führt zudem zu Verlust an Performance (und somit Zeit).

Ist die SQL Server-Plattform installiert, so sind folgende Aufgaben zur Pflege einer Datenbank (außer TempDB) sinnvoll und empfohlen:

  • Index/Statistik Optimierung (für Systemdatenbanken nicht erforderlich)
  • Datenbankkonsistenzprüfung (DBCC CheckDB)
  • Datenbanksicherung (Backup)
    • Vollsicherung
    • Differential
    • Transaction Log (für Datenbanken im Wiederherstellungsmodell „Voll“)
  • Bereinigen der Datenbankwartung (CleanUp)

Nun könnte man meinen, dass man nur entsprechende Verfahren für alle Datenbanken einrichten muss und die Aufgabe ist erledigt. Leider ist dies nicht so, denn einige Datenbank-Anwendungen erledigen ein Teil dieser Aufgaben bereits automatisch. Somit ist im ersten Schritt zu prüfen, welche Anwendung welche der o. g. Aufgaben zur Pflege einer Datenbank bereits übernimmt (z. B. SharePoint 2013: „For Maintenance Plans, avoid using Update Statistics as well as the Reindex or Rebuild Index tasks as SharePoint handles those via Timer Jobs.“) und für welche Sie diese selbst bereitstellen müssen. Außerdem sind besondere Betriebszeiten bei der Planung zu beachten. So ist es beispielsweise unsinnig, eine Datenbankvollsicherung zu einer Zeit durchzuführen, wenn alle Benutzer an der Datenbank arbeiten. Zusätzlich gibt es Wechselwirkungen zwischen den einzelnen Aufgaben, sodass sie zeitlich so geplant werden müssen, dass sie sich nicht überschneiden. Des Weiteren gibt es für die Ausführung der Datenbankwartung eine definierte Reihenfolge z. B. sollte eine Datenbank nur dann gesichert zu werden, wenn sie konsistent ist (keine Fehler beinhaltet).

Zur Ausführung der Datenbankwartung gibt es mehrere Lösungen:

  • SQL Server Agent
    • Master Server (MSX)
  • Windows Task Scheduler
  • Jobsteuerungssystem (Fremdanbieter)

Zusätzlich gibt es speziell im Backup-Bereich noch Individuallösungen, die auch in der Lage sind Datenbankwartungsaufgaben unabhängig auszuführen.

Zum Ausführen der Datenbankwartung gibt es keine Ideallösung, sondern abhängig von Ihren Anforderungen müssen Sie sich für eine Lösung entscheiden. Ein Wechsel zwischen den Lösungen ist sehr aufwendig und technisch kaum umsetzbar (außer man macht alles neu). Eine Kombination von Lösungen ist möglich, jedoch erhält man dann sehr schnell sich überschneidende Aufgaben (z. B. während eines Backups werden Indexoptimierungen ausgeführt).

Für eine Datenbankwartung kann man eine für alle Datenbanken einheitliche Lösung einführen (einfachste Lösung), man kann Datenbankgruppen bilden, man kann Konfigurationen z. B. in SQL Server Tabelle verwalten, wann welche Wartungsaufgabe für welche Datenbank ausgeführt werden soll oder man kann für jede Datenbank eine individuelle Lösung festlegen (aufwendig und wartungsintensiv, jedoch die höchste Flexibilität).

Zur Umsetzung der Datenbankwartung gibt es verschiedene Verfahren:

  • Wartungspläne (Maintenance Plans)
  • SQL Server Integration Services (SSIS)
  • TSQL
  • PowerShell
  • Höhere Programmiersprache (C#)

Eine Ideallösung gibt es auch dafür nicht und jedes Unternehmen muss sich schlussendlich für ein ihren Anforderungen entsprechendes Verfahren festlegen. In der Praxis kommen oft verschiedene Verfahren innerhalb eines Unternehmens und sogar einer Datenbankinstanz zum Einsatz. Solche Vorgehensweisen verkomplizieren den Wartungs- und Pflegeaufwand dieser Lösungen.

Vergleich der unterschiedlichen Verfahren

Wartungspläne

Die Erstellung von Wartungsplänen ist in SQL Server Management Studio integriert und die Pläne können mit einem Assistenten erstellt

clip_image002 clip_image004

clip_image006 image

image

und mit einem grafischen Designer bearbeitet werden:

image

Dadurch sind sie optisch ansprechend und gut lesbar (auch ohne Programmierkenntnisse).

Ein Wartungsplan kann sich in verschiedene Unterpläne (sub plans) gliedern. Die voneinander unabhängig ausgeführt werden können. Der Vorteil dieser Gliederung besteht darin, mehrere Wartungsaufgaben in einem Objekt zusammenzufassen und dadurch lassen sich diese leichter auf unterschiedliche Systeme verteilen. Jedem Unterplan kann ein Zeitplan zur Ausführung zugewiesen werden. Zu jedem Zeitplan eines Unterplans wird automatisch durch das SQL Server Management Studio ein SQL Server Agent Job auf der gleichen Instanz angelegt. Die Zeitsteuerung der Ausführung des SQL Server Agent Jobs erfolgt direkt im Wartungsplan und wird dann in den dazugehörenden Agent Job übertragen. Manuelle Anpassungen an der Zeitsteuerung z. B. direkt im SQL Server Agent Job sind nicht zu empfehlen.

Bei Wartungsplänen handelt es sich um eine auf Wartungsaufgaben reduzierte Version von SQL Server Integration Services (SSIS). Dadurch steht auch nur ein geringerer Funktionsumfang im Vergleich zu SSIS zur Verfügung. Die Aufgaben (Tasks) eines Wartungsplanes werden bei der Ausführung dynamisch in TSQL-Code umgewandelt. Dadurch ist nicht immer genau klar, was, wann und wie ausgeführt wird (Nachvollziehbarkeit).

Zu einem Wartungsplan lassen sich mehrere Verbindungen zuweisen, insofern der SQL Server Agent Service-/Proxy Account über die entsprechenden Rechte zum Ausführen der Job-Schritte hat. Dabei wird das Paket auf dem aktuellen Server ausgeführt und die Befehle an die anderen Server gesendet.

image

Dadurch sparen Sie sich die Verteilung der Pakete auf verschiedene Systeme und Sie können die Job-Verarbeitung von einem zentralen Punkt aus steuern. Als Nachteil handeln Sie sich jedoch den Verlust der individuellen Behandlung von Datenbanken ein.

Insofern der SQL Server Agent als Masterserver (MSX) in einer Multiserver-Umgebung konfiguriert ist, kann ein Paket von einer zentralen Instanz aus auch automatisch auf mehrere Systeme verteilt werden:

image

Die Konfiguration eines SQL Server Agent als Masterserver ist etwas aufwendig, jedoch ersparen Sie sich damit aufwendige Verteilungen der Wartungspläne auf mehrere Systeme. Eine gute Anleitung zum Einrichten einer solchen Umgebung finden Sie unter https://sqlship.wordpress.com/category/multi-server-administration/.

In einer SQL Server-Instanz werden die Wartungspläne in der MSDB-Datenbank gespeichert. Die Berechtigungen (z. B.  zur Ausführung von Wartungspaketen) kann über entsprechende Rollen dieser Datenbank gesteuert werden. Durch die Ablage der Wartungspläne in der MSDB ist die Übertragung auf eine andere SQL Server Instanz aufwendig und erfordert eine betriebsbereite SSIS-Instanz (http://www.varindersandhu.in/2014/02/14/sql-server-migrate-transfer-maintenance-plan-one-instance-another/). Alternativ kann man die Wartungspläne als SSIS-Pakete im XML-Format auch aus der MSDB exportieren. Die einfachste Möglichkeit um ein Wartungspaket von einer SQL Server-Instanz auf eine andere zu übertragen ist die Verwendung des Kommandozeilen-Tools DTUtil:

dtutil /Quiet /COPY SQL;“Maintenance Plans\DBMaintenance“ /SQL „Maintenance Plans\DBMaintenance“ /SOURCESERVER <srcServer> /DESTSERVER <destServer>

Um den vollständigen Pfadnamen eines Wartungsplans zu erhalten, können Sie folgende TSQL-Abfrage verwenden:

select
    case foldername
        when '' then '"' + [name] + '"'
        else '"' + foldername + '\' + [name] + '"'
    end
from msdb.dbo.sysssispackages pkg inner join msdb.dbo.sysssispackagefolders fld
on pkg.folderid = fld.folderid

Mit dem SQL Server Management Studio erstellte Wartungspläne können mit SQL Server Data Tools für Business Intelligence (SSDT BI) weiter bearbeitet und um zusätzliche Funktionen angereichert werden (siehe nächstes Kapitel). Abhängig von den implementierten Tasks kann es dann jedoch erforderlich werden, SQL Server Integration Services (SSIS) als zusätzlichen Dienst auf SQL Server verwenden zu müssen.

Hinweis: Eine Versionierung der Wartungspakete in einem Versionsveraltungssystem wie z. B. Team Foundation Server oder GIT ist im SQL Server Management Studio nicht möglich. Um eine Versionierung durchzuführen, können Sie das Paket entweder ins Filesystem exportieren und dort versionieren oder SSDT BI zur Versionierung verwenden.

SQL Server Integration Services

Bei dieser Komponente handelt es sich um einen eigenen Service von SQL Server, dessen Hauptaufgabe in Extract/Transform/Load-Prozessen (ETL) von Daten besteht. Um Programme (Pakete) für SQL Server Integration Services (SSIS) zu erstellen, können Sie z. B. die SQL Server Data Tools für Business Intelligence (SSDT BI) verwenden.

Hinweis: Bei SQL Server Data Tools für Business Intelligence handelt es sich um ein spezielles Tool, das von Microsoft kostenlos bereitgestellt wird. Bei der Verwendung dieses Tools sind einige Punkte zu beachten, die ich später in einem eigenem Blogbeitrag noch intensiver beleuchten möchte.

Für diese Aufgabe stehen sehr umfangreiche und komplexe Aufgabenpakete (Tasks) zur Verfügung. Zusätzlich existieren in der Taskliste auch die entsprechenden Aufgaben für Wartungspläne. SSIS-Pakete lassen sich ähnlich wie Wartungspläne im SQL Server Management Studio mit einem grafischen Designer (SQL Server Data Tools für Business Intelligence) bearbeiten. Seit SQL Server 2012 sind SQL Server Integration Services Projekte auch in SQL Server Management Studio unter einem eigenen Punkt im SQL Server-Instanzbaum integriert und können von dort aus administriert werden insofern dies entsprechend konfiguriert wurde.

Hinweis: Wartungspläne sind in einem eigenen Bereich des SQL Server-Instanzbaum im SQL Server Management Studio unter Verwaltung\Wartungspläne und nicht unter den Integration Services-Katalogen zu finden.

image

Im Folgenden zeige ich den Ablauf auf, um Wartungspläne mit SQL Server Data Tools für Business Intelligence weiter zu bearbeiten. Dazu gibt es unterschiedliche Möglichkeiten:

  1. Unter Verwendung einer SQL Server Integration Services-Instanz.
    Verbinden Sie sich mit dem SQL Server Management Studio mit der entsprechenden SSIS-Instanz (Connect à Integration Services) und wechseln in dem Objektbaum auf das entsprechende Wartungspaket. Im Kontextmenü dieses Paketes haben Sie dann die Möglichkeit das Paket zu exportieren:
    image
    Im nachfolgenden Dialog ist es wichtig als Paketspeicherort das „Files System“ auszuwählen und unter Paketpfad können Sie das Verzeichnis/Dateinamen angeben, wohin das Paket exportiert werden soll.
    clip_image014
  2. Wie bereits im vorherigen Kapitel Wartungspläne beschrieben, können Sie das Paket auch durch Ausführen einer Abfrage

select
name as [Maintenance Plan]
, cast(cast(packagedata as varbinary(max)) as xml) as Paket
from msdb.dbo.sysssispackages
where packagetype = 6
and name = ‚DBMaintenance‘

aus dem SQL Server extrahieren und als SSIS-Paket speichern.

clip_image016

Klicken Sie danach auf die entsprechende XML-Struktur im Feld „Paket“, wird diese XML-Struktur in einem eigenem Fenster im Management Studio geöffnet und sie können dann die Datei im Dateisystem mit der Erweiterung dtsx abspeichern:

clip_image018

3. DTUtil

dtutil /Quiet /COPY SQL;“Maintenance Plans\DBMaintenance“ /File „C:\TEMP\DBMaintain.dtsx“ /SOURCESERVER srcServer

Datenbankauswahl für Wartungsaufgaben

Wie bereits einleitend beschrieben, hat möglicherweise jede Datenbank andere Anforderungen an die Datenbankwartung. Innerhalb eines Wartungsplans lassen sich für einzelne Aufgaben Datenbanken in Gruppen aufteilen oder einzelne Datenbanken auswählen:

clip_image036

Besonders der Bereich „These databases“ hat jedoch den Nachteil, dass Änderungen an der Instanz z. B. wenn eine neue Datenbank angelegt wird, diese nicht automatisch mit in die Wartung mit aufgenommen wird. In einem solchen Fall muss der DB-Administrator manuell eingreifen, um die Datenbank in die Wartung mit aufzunehmen.

Verwendet man keine Wartungspläne ist man flexibler, hat jedoch auch den Nachteil, dass Wartungsinformationen speziell dann, wenn nur für bestimmte Datenbanken Wartungsaufgaben durchgeführt werden sollen, diese irgendwo gespeichert werden müssen. Dafür bieten sich beispielsweise die erweiterten Eigenschaften einer Datenbank an:

clip_image038

Programmtechnisch (TSQL, PowerShell, …) kann man nun kontrollieren, ob die entsprechende Eigenschaft gesetzt ist, um die Ausführung der Wartungsaufgabe zu verhindern. Der große Vorteil dieser Vorgehensweise besteht darin, dass ich Datenbanken zwischen SQL Server-Instanzen verschieben kann, ohne mich jeweils mit dem Thema „Datenbankwartung“ beschäftigen zu müssen à Voraussetzung ist natürlich, dass auf allen Servern die gleichen Datenbankwartungsmaßnahmen eingesetzt werden.

Multiple Subplans

Unterpläne (Subplans) kommen nur in Wartungspläne vor. Jeder Unterplan ist ein eigenständiges Skript und kann einen eigenen Zeitplan (Scheduler) haben. Jedoch besteht auch die Möglichkeit einen Zeitplan für einen gesamten Wartungsplan zu definieren.

Der Vorteil von mehreren Unterplänen in einem Wartungsplan besteht in der leichteren Pflege (besser ein Wartungsplan als viele) und der leichteren Übertragung

Workflow

Aufgaben können in Form eines Workflows oder einzeln abgearbeitet werden. Die Verarbeitung innerhalb eines Workflows hat den Vorteil, dass keine Abhängigkeiten und zeitlichen Überlagerungen auftreten können.

Vergleich am Beispiel eines Wartungsplans

clip_image040 clip_image042

Zum Bearbeiten des Paketes müssen Sie im SQL Server Data Tools für Business Intelligence ein neues Projekt auf Basis der Vorlage „Integration Services-Projekt“ anlegen.

clip_image020

clip_image022

Anschließend können Sie das zuvor im Dateisystem gespeicherte SSIS-Paket als vorhandenes Paket dem Projekt hinzufügen:

clip_image024

clip_image026

Wenn Sie das SSIS-Paket öffnen, werden Sie für jeden Subplan einen eigenen Bereich sehen. Innerhalb eines Containers innerhalb des Subplans befinden sich die Tasks, die Sie vorher im Wartungsplan definiert haben.

Am Ende des Bereichs eines Subplans sehen Sie eine eigene Task „Berichtstask für Unterplan <GUID>“. Bei dieser Task handelt es sich um eine Spezialtask von Microsoft, die standardmäßig im SSDT BI nicht zur Verfügung steht (somit können Sie keine eigenen Tasks anlegen). Jedoch können Sie die Eigenschaften dieser Task auch aus dem SSDT BI entsprechend Ihren Anforderungen anpassen.

clip_image028

Transact-SQL (T-SQL)

T-SQL ist die Basissprache von SQL Server. Alle Befehle zur Kommunikation mit SQL Server sind in T-SQL implementiert (DML, DDL, DCL). Auch wenn Sie SQL Server über ein anderes Interface steuern z. B. SQL Server Management Objects (SMO), so werden auch diese Kommandos intern wieder zu T-SQL umgewandelt und durch den SQL Server ausgeführt. Neben der Verarbeitung von Befehlen durch den SQL Server stehen im T-SQL einige Befehle zur Ablaufsteuerung zur Verfügung.

Mit T-SQL und unter Verwendung von SQL Server Agent Jobs, lassen sich nun individuelle Wartungsskripte zusammenstellen, die entsprechend Ihren Anforderungen angepasst werden können. Das folgende Beispiel stellt die Verwendung von TSQL in einem SQL Server Agent Job zum Backup einer Datenbank dar.

clip_image030

Um nicht für jede Datenbank eigene Jobs schreiben zu müssen, können Sie mit Platzhaltern, wie in dem folgenden Beispiel gezeigt, arbeiten:

BACKUP DATABASE $(ESCAPE_SQUOTE(A-DBN)) TO DISK = N’\\server\path\backup\$(ESCAPE_SQUOTE(A-DBN))_$(ESCAPE_SQUOTE(DATE))_$(ESCAPE_SQUOTE(TIME)).bak‘ WITH FORMAT, INIT, SKIP

Der Pflegeaufwand einer solchen Lösung ist sehr gering, da nur eine Komponente von SQL Server, der SQL Server Agent, involviert ist. Die Programmiersprache T-SQL ist einfach anzuwenden, sollte von jedem SQL Server DBA beherrscht werden und ist von Microsoft in den Books Online und in der Hilfe zum SQL Server ausführlich dokumentiert.

Damit nicht jeder für sich anfangen muss, entsprechende Lösungen zu designen, gibt es zwischenzeitlich einige Lösungen auf Basis von T-SQL zur Wartung von Datenbanken. Eine der umfangreichsten Lösungen ist die MaintenanceSolution von Ola Hallengren. Diese Lösung ist einfach zu installieren, zu konfigurieren und wird durch den Programmierer kontinuierlich weiterentwickelt. Diese (kostenlose) Lösung wird aktuell von Microsoft Consulting Services und von vielen SQL Server Consultants weltweit empfohlen:

“The best starting point for building your own maintenance plan is the comprehensive and free script from Ola Hallengren. That’s what I recommend to my clients.”
Paul S. Randal

Dieser Empfehlung kann ich mich nur anschließen.

T-SQL hat jedoch aufgrund einiger Limitierungen eine Reihe von Nachteilen:

· Der zur Verfügung stehende Befehlssatz für Ablaufsteuerung ist gering (im Vergleich zu anderen Programmiersprachen) und einige Anforderungen lassen sich dadurch nur schwer realisieren.

· Funktionen und Prozeduren müssen als kompilierte Objekte in SQL Server abgelegt werden

· Parallelverarbeitung ist nicht vorgesehen

· Einige Sprachkonstrukte wie z. B. Cursor sind ungewöhnlich für Programmierer und dadurch schwer zu implementieren.

PowerShell

In den letzten Jahren hat sich für viele Wartungsaufgaben im Windows-Umfeld PowerShell als optimales Werkzeug erwiesen. Viele Aufgaben können damit schnell und unkompliziert ausgeführt werden.

Powershell ist für die Datenbankwartung ein sehr flexibles Werkzeug. Es kann Dank umfangreicher Tokenunterstützung und die bereits erfolgte Integration des SQL Server PowerShell Providers (SQLPS) in den SQL Server Agent sehr einfach angewendet werden, um auch komplexe Anforderungen abzubilden.

Das folgende Beispiel eines kleinen PowerShell-Skripts soll die Verwendung von Token in Auftragsschritten demonstrieren:

$Servername = „$(ESCAPE_SQUOTE(SRVR))“
if (!$Servername.Contains(„\“)) {
    $Servername+=“\Default“
}
get-childitem „SQLServer:\\SQL\$Servername\databases“ -Force | select-object name

clip_image032

Im Folgenden habe ich Ihnen ein etwas komplexeres Skript erstellt, mit dem Sie über eine Liste von Servern parallel verschiedene Aufgaben ausführen können. Die Ausführung erfolgt hierbei vom lokalen Server aus und wird nur als Befehl an die in der Liste aufgeführten Server weitergeleitet. Hierbei ist keine PowerShell Remoting erforderlich. Die im SQL Statement ($SQL) angegebene Query kann entsprechend Ihren Anforderungen individuell angepasst werden.

WorkFlow Start-Maintenance {
param(
    [Parameter(Mandatory=$true)]
    [string[]]$ServerInstances, # string array to hold multiple sql instances
    [String]$Query = „“
)

ForEach -Parallel ($Servername in $ServerInstances) {
    Sequence {
        InlineScript {
            Import-Module –Name ‚SQLPS‘ –DisableNameChecking
            $s = $using:Servername
            if (!$s.Contains(„\“)) {
                $s+=“\Default“
            }
            $Query = $using:Query
            Get-ChildItem -Path „SQLServer:\\SQL\$s\databases“ -Force | Where-Object {$PSItem.Name -ne „tempdb“} | ForEach-Object {
                Invoke-Sqlcmd -ServerInstance $using:Servername -Database $($PSItem.Name) -QueryTimeout 60000 -Query $($Query.Replace(„@DBName@“, $PSItem.Name))
            }
       }
   }
}
}

$SQL = @“
    USE [@DBName@]
    GO
    select @@Servername as Servername, name as Databasename from sys.databases where database_id = db_id()
    GO
„@

Start-Maintenance -ServerInstances „SV205304“, „SV198306“ -Query $SQL | Select-Object Servername, Databasename

https://gallery.technet.microsoft.com/scriptcenter/Schedule-Ola-Hallengrens-a66a3c89

Höher Programmiersprache

Was mit T-SQL oder PowerShell möglich ist, kann auch mit einer höheren Programmiersprache wie z. B. C#, VB.NET umgesetzt werden. Der Vorteil von C# ist die hohe Flexibilität und Performance. Als Nachteile sind jedoch der sehr hohe Programmieraufwand und Projektaufwand zu sehen. Des Weiteren sind Anpassungen an der Anwendung immer abhängig von der Verfügbarkeit der Programmierer. Außerdem sind für die Ausführung von Programmen spezielle Berechtigungen im SQL Server erforderlich.

Der folgende Screenshot beinhaltet nur ein Beispiel. Das dafür erforderliche Programm existiert nicht und müsste noch erstellt werden.

clip_image034

Da der Einsatz einer höheren Programmiersprache für die Umsetzung von Wartungsaufgaben sehr aufwendig ist, möchte ich dieses Kapitel auch nicht näher beleuchten. Sollten Sie trotzdem Fragen dazu haben, sprechen Sie mich gerne direkt an.

Zusammenfassung

Datenbankwartung ist ein komplexes Thema. Vernachlässigen Sie diese Aufgaben riskieren Sie mehrere kritische Probleme für Ihr Unternehmen wie z. B. Datenverlust und Performance. Die Verantwortung dafür trägt immer der Datenbankadministrator. Im meiner Rolle als Consultant war ich bereits in einigen Unternehmen, bei denen der DBA gefeuert wurde, weil er solche Themen vernachlässigt hat. Ich möchte damit nicht gleich den Teufel an die Wand malen und, nachdem Sie diesen Artikel bis hierhin gelesen haben, gehe ich davon aus, dass Ihnen das Thema auch nicht egal ist.

Ich hoffe, ich konnte Ihnen hiermit einige Anregungen liefern und sollten Sie noch Fragen haben, freue ich mich über Kommentare zu diesem Beitrag oder sprechen Sie mich direkt an.

Advertisements
Über

Die IT-Welt wird immer komplexer und zwischen den einzelnen Komponenten gibt es immer mehr Abhängigkeiten. Nachdem ich durch meine tägliche Arbeit immer wieder vor der Herausforderung stehe, komplexe Probleme zu lösen, möchte ich diese Seite dafür verwenden, Euch den einen oder anderen Tipp zu geben, wenn Ihr vor ähnlichen Aufgabenstellungen steht.

Veröffentlicht in SQL Server, Wartung

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: