none
Backup einer Datenbank in einer anderen Instanz RRS feed

  • Frage

  • Hallo!

    Ich habe folgendes Problem: Wir betreiben/administrieren diverse Datenbanken auf diversen Servern/Instanzen. Dabei liegt im Regelfall eine Testdatenbank und eine produktive vor. Zu Testzwecken wird oftmals beauftragt, eine Produktiv- auf eine Testdatenbank zu spiegeln. Beide Datenbanken liegen auf dem gleichen Server, aber in unterschiedlichen Instanzen.

    Ich möchte per Skript folgende Schritte ausführen lassen:

    1. Backup ProduktivDB

    2. Restore der ProduktivDB in die TestDB

    Teil 2 klappt hervorragend; allerdings schaffe ich es nicht, in dem Skript eine Sicherung der Produktivdatenbank anlegen zu lassen. Ich habe in der Testinstanz einen Verbindungsserver (Produktivinstanz) definiert, der dem sa der Testinstanz in der Serverrolle public die Datenbankrolle db_backupoperator zuweist. Der Befehl

    backup database ServerName\Instanzname.dbName

    to disk='f:\backupname.bak' with init;

    wirft mir zwei Fehlermeldungen:

    Meldung 102, Ebene 15, Status 1, Zeile 4Falsche Syntax in der Nähe von '\'.

    Meldung 319, Ebene 15, Status 1, Zeile 5Falsche Syntax in der Nähe des WITH-Schlüsselworts. Falls diese Anweisung ein allgemeiner Tabellenausdruck, eine XMLNAMESPACES-Klausel oder eine CHANGE TRACKING CONTEXT-Klausel ist, muss die vorherige Anweisung mit einem Semikolon abgeschlossen werden.

    Wie muss ich die zu sichernde Datenbank referenzieren, um das Backup ausführen zu lassen, oder wo liegt mein Denkfehler?


    Montag, 2. März 2015 09:26

Antworten

  • Die einfachen Anführungszeichen musst Du "quoten" = verdoppeln:

    DECLARE @sql nvarchar(1000);
    SET @sql = 'backup database dbName to disk=''f:\backupname.bak'' with init;';
    PRINT @sql
    


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Montag, 2. März 2015 10:35

Alle Antworten

  • Hallo Tekee,

    der BACKUP (Transact-SQL) Befehl lässt es so nicht zu einen anderen Server zu adressieren.

    Du könntest den Backup Befehl als dynamisches SQL schreiben und dann per EXECUTE mit der AT Klausel gegen den Verbindungsserver ausführen.

    Mini-Beispiel, wenn Du das auf dem Prod-Server ausführst, solltest Du den Namen das anderen Server erhalten:

    DECLARE @sql nvarchar(1000);
    SET @sql = 'SELECT @@ServerName'
    
    EXECUTE (@sql) AT [NameDeinesLinkedServers]


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Montag, 2. März 2015 09:42
  • Okay, das ist auf jeden Fall schon mal eine Erklärung, warum es SO nicht funktioniert. :)

    Bei Deinem Skript würde ich den  'SELECT @@ServerName'-Teil durch das BackUp-Statement ersetzen, was dann durch das "EXECUTE" auf der LinkedServer-Instanz ausgeführt würde, statt auf der Testinstanz selbst!?

    Montag, 2. März 2015 09:46
  • Genau, das mit @@ServerName war nur zur Demo, dass das Statement hier wirklich auf dem anderen, Linked Server ausgeführt wird und nicht auf dem man aktuell angemeldet ist.

    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Montag, 2. März 2015 10:22
  • Das hat schon mal eine Menge geholfen, die beiden eingangs erwähnten Fehlermeldungen sind jetzt weg :)

    Allerdings mag er jetzt den Backslash im "to disk"-Ziel nicht mehr und verweigert die Mitarbeit :-/ Hast Du dafür auch einen Tipp? Ich vermute mal, dass die geschachtelten Anführungszeichen so nicht gehen - ein Ersetzen des äußeren Paares durch doppelte Anführungszeichen wirkt aber auch nicht, dann wertet er das als Spaltennamen einer Tabelle (und findet natürlich nix). Gibt es eine Möglichkeit, die notwendigen Anführungszeichen zu maskieren?

    Montag, 2. März 2015 10:28
  • Die einfachen Anführungszeichen musst Du "quoten" = verdoppeln:

    DECLARE @sql nvarchar(1000);
    SET @sql = 'backup database dbName to disk=''f:\backupname.bak'' with init;';
    PRINT @sql
    


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Montag, 2. März 2015 10:35
  • Vielen herzlichen Dank, funktioniert - eine 12-GB-Datenbank ist jetzt mit einem Doppelklick und 8 Minuten Warten auf die Testdatenbank kopiert.

    Als Rückgabe an die Community (und zur unauffälligen Kontrolle) das vollständige Skript:

    use master
    
    -- Neues Backup der Quelldatenbank anlegen, evtl. vorhandene Datei wird überschrieben (init)
    -- da andere Instanz, ist dynamisches SQL notwendig!
    
    DECLARE @sql nvarchar(1000);
    SET @sql = 'backup database [DB_Name]
    to disk=''[Backup-Dateiname]'' with init;'
    
    EXECUTE (@sql) AT [Verbindungsserver]
    
    -- Zugriffe auf alte Zieldatenbank beenden, da sonst ein Restore scheitert
    
    ALTER DATABASE [DB_Name] SET SINGLE_USER WITH ROLLBACK IMMEDIATE
    
    -- Hier die Datenfilezahl und -namen anpassen; je eine move-Zeile für ein Datenfile.
    -- Bestehende Datenbank wird überschrieben (With replace)
    -- Anzugeben sind die logischen Datenfilenamen der Quell- und die Dateinamen der ZIELdatenbank
    
    restore database [DB_Name]
    from disk='[Backup-Dateiname]'
    WITH replace,
    move '[QuelldbLogicalfilename]' to  '[ZieldbPhysicalfilename]',
    move '[QuelldbLogicalfilename]' to  '[ZieldbPhysicalfilename]'
    
    Voraussetzungen: Die Quelldb liegt in einer Instanz, die als LinkedServer definiert ist; die RPC-Optionen der LinkedServer-Verbindung sind beide auf "true", der User, der die Verbindung erzeugt, hat die db_BackUpOperator-Rolle der zu sichernden Datenbank

    Montag, 2. März 2015 11:04