Sind direkte SQL Server-Upgrades so unangebracht wie früher?

78

Ich arbeite seit SQL Server 6.5 mit SQL Server ein und aus. Der alte Rat, der mir immer noch in den Sinn kommt, war, niemals ein direktes Upgrade durchzuführen.

Ich aktualisiere derzeit meine 2008 R2 DEV- und TEST-Systeme auf SQL Server 2012 und muss dieselbe Hardware verwenden. Der Gedanke, meine Reporting Services-Konfiguration nicht wiederherstellen zu müssen, ist sehr attraktiv, und ich bin zeitlich sehr konkurrenzfähig. Es handelt sich weder um Analysedienste noch um ungewöhnliche oder nicht standardmäßige Vorgänge. Es werden nur das Datenbankmodul und die Berichterstellungsdienste installiert.

Hat jemand ernsthafte Probleme mit vorhandenen Upgrades gehabt? Oder sollte ich meine Position zu In-Place-Upgrades neu bewerten?

Beschädigte Ware
quelle
Ich habe mich für ein Inplace-Upgrade auf einem Server mit Reporting Services-Installation entschieden. Das einzige Problem, auf das ich gestoßen bin, war der Versuch, das Import-Export-Tool in SSMS mit nativem Client 11 zu verwenden. Der Versuch, die Umwandlung durchzuführen, schlug mit einem Fehler über nicht erkannte Datentypen fehl. Die Problemumgehung bestand darin, das Paket zu speichern und in SQL Data Tools (BIDS-Ersatz) auszuführen, was problemlos funktionierte. Ich denke, das muss damit zu tun haben, dass die Konfigurationsdatei für SSIS 2008 nicht überschrieben wird. Es ist mir später aufgefallen, dass Sie den nativen Client möglicherweise einfach auf 10
zurücksetzen können

Antworten:

92

Wirklich kurze Antwort - In Place ist in Ordnung. Sie können Ihre Konfiguration anschließend überprüfen und die Best Practices für SQL Server 2012 implementieren.

Eine längere Antwort auf SQL Server-Upgrades / -Migrationen

Das ist also eine Ansichtssache und es gibt nicht unbedingt eine falsche oder richtige Antwort, aber ich bevorzuge aus vielen Gründen Upgrades im Migrationsstil anstelle von In-Place-Upgrades. Davon abgesehen hatten einige meiner Kunden aus verschiedenen Gründen keine andere Wahl, als ein In-Place-Upgrade durchzuführen. Seit SQL Server 2005 waren In-Place-Upgrades nicht mehr so ​​schlecht wie früher.

Warum bevorzuge ich eine Migration zu einem direkten Upgrade?

  • Einfacheres Rollback - Wenn etwas schief geht, können Sie ein Rollback durchführen, indem Sie einfach sagen: "Wir haben das Upgrade abgebrochen. Bitte ändern Sie die Verbindungszeichenfolgen auf den alten Server, während wir das Problem beheben." Mit einem In-Place-System beheben Sie das Problem, oder Sie sind inaktiv.
  • Hardware aktualisieren - Hardware ändert sich schnell. Bei Hardware, die vor 4 Jahren für Ihr Unternehmen richtig war, aber heute und in den nächsten vier Jahren mit einem In-Place-Upgrade nicht mehr richtig ist, können Sie sich schnell zurechtfinden. Sie werden wahrscheinlich ohnehin irgendwann eine Migration für die neue Hardware durchführen müssen.
  • Fühlen Sie sich besser - sicher ... Diese ist subjektiv, aber es fühlt sich gut an, zu wissen, dass Sie mit einer neuen Betriebssysteminstallation beginnen, einer neuen SQL-Installation ohne Spinnweben von der Person, die vor Ihnen im Einsatz war (oder von der Sie vorher wussten, was Sie wussten) Heute) könnte dies möglicherweise in Zukunft zu Kopfschmerzen führen.
  • Neues Betriebssystem - Eine Migration gibt Ihnen die Möglichkeit, mit einer neuen Betriebssystemversion zu beginnen, wenn Sie nicht auf dem neuesten und aktuellsten Stand sind.
  • Sie können es testen - Sie möchten schon immer eine Reihe von Baselines auf einem neuen Computer erhalten, bevor Sie SQL installieren und es mit Datenbanken und der Nutzung trüben? Sie können das jetzt tun.
  • Manchmal ist es einfacher, sich über bewährte Methoden zu informieren. Möglicherweise war das SQL Server-Dienstkonto ein lokaler Administrator. Möglicherweise hat Builtin Administrators die SA-Serverrolle. Vielleicht wurden die Dinge schon einmal zusammen gehackt, damit es funktioniert. Sie können das alles beheben und neu anfangen.
  • Kostenlose Testumgebung und zusätzlicher Schlaf - Es ist ein großer Vorteil, eine Umgebung zu haben, in der Sie vor dem eigentlichen Stichtag arbeiten können, wenn Sie diese neue Umgebung zum Leben erwecken. Wenn Sie eine Migration in eine neue Umgebung durchführen, können Sie sie während der Geschäftszeiten weit vor dem eigentlichen Stichtag erstellen und auf vielfältige Weise im Voraus testen. Sie können tagelang vollständige Regressionstests für alle Anwendungen und Systeme ausführen und sind sich sicher, bevor Sie den endgültigen Satz an Wiederherstellungen / Anhängen und das Überschneiden aller Anwendungen sowie den Zugriff auf die neue Umgebung durchführen.
  • Sie müssen nicht alles auf einmal tun - Eine sehr häufige Situation, auf die ich stoße, ist eine Umgebung, die versucht, sich auf nur wenige Instanzen zu konsolidieren. Vielleicht eine pro Version, vielleicht eine pro "Tier" und Version. Viele dieser Projekte haben unterschiedliche Zeitpläne für verschiedene Anwendungen und Datenbanken, basierend auf Tests, Projektplänen und der Aktualität der Herstellerzertifizierung. Durch die Migration können Sie die bereitgestellten Datenbanken verschieben, wenn sie bereit sind, und weiterhin Anforderungen für die Datenbanken verarbeiten, die aus dem einen oder anderen Grund nicht verschoben werden können.

Wohlgemerkt ich sage nicht , Sie haben dies als eine Migration zu tun. In-Place funktioniert und es funktioniert gut, wenn Sie nicht planen, neue Hardware in Ihrem Budget zu kaufen, und dies für dieses Upgrade nicht tun können. Die Unterstützung beim Upgrade-Prozess ist so viel besser als in den 6,5 Tagen, sodass Sie sich dadurch nicht in eine schlechte Position bringen.

Wenn Sie vorhaben, eine In-Place-Migration für dev / test durchzuführen, aber eine Migration für die Produktion durchführen möchten, sollten Sie vor der Produktion mindestens eine Migration durchführen. Auf diese Weise können Sie Ihre Checkliste im Voraus ausarbeiten und sich mit potenziellen Problemen befassen, an die Sie nicht gedacht haben.

Anhängen / Trennen vs. Sichern / Wiederherstellen für Migrationen

Wenn Sie sich für den Migrationsansatz entscheiden, gibt es noch eine Entscheidung, über die Sie möglicherweise noch debattieren. Auf diese Weise verschieben Sie Ihre Datenbank in die neue Umgebung. Sie können Ihre Datenbank entweder vom alten Server trennen und an den neuen Server anhängen oder sie sichern und dort wiederherstellen.

Ich bevorzuge Backup / Restore. Der größte Vorteil, den ich von Detach / Attach höre, ist die Zeitersparnis. Für mich gewinnt Backup / Restore aus ein paar Gründen:

  • Behalten Sie den Zugriff auf die alte - Dies ermöglicht es Ihnen, weiterhin eine zugreifbare Datenbank auf dem Quellserver zu haben. Das Trennen / Anhängen sollte dasselbe tun, es sind jedoch einige Schritte erforderlich, und es besteht Raum für menschliches Versagen beim Trennen / Anhängen, was dies erschweren könnte.
  • Sie garantieren, dass Sie über eine Sicherung verfügen. Anstatt nur eine Datenbank von einer Trennung zu nehmen und möglicherweise einen Sicherungsschritt zu vergessen, haben Sie sichergestellt, dass Sie diese Sicherung erstellt haben.
  • Menschliches Versagen - Wenn Sie die falsche Datei löschen, vergessen, wohin Sie etwas senden oder auf andere Weise Ihre Schritte durcheinander bringen, besteht ein hohes Risiko, wenn Sie die Daten und Protokolldateien für Ihre Datenbank verschieben. Jetzt können Sie dies abmildern, indem Sie kopieren, anstatt zu schneiden (und wenn Sie sich lösen, sollten Sie die Gewohnheit des Ausschneidens und Einfügens aufgeben), aber Sie könnten trotzdem Unordnung stiften. SQL Server sperrt diese Dateien nicht mehr und es ist einfach zu einfach, eine Datei aus Versehen zu löschen, um dies zu riskieren.
  • Es ist nicht wirklich so langsam - Sichern und Kopieren dauert etwas länger, aber ich bin nicht bereit, das zusätzliche Risiko dafür zu tragen. Tatsächlich können Sie mithilfe eines vollständigen Wiederherstellungsmodells und von Protokollsicherungen die Ausfallzeit für Umschaltungen noch verringern, wie im Abschnitt "So beschleunigen Sie den Migrationsansatz" weiter unten beschrieben.

Wenn Sie sich für die Sicherung / Wiederherstellung entscheiden, ist Ihre alte Quellendatenbank weiterhin online. Ich möchte diese Datenbank nach dem Backup offline schalten. Manchmal gehe ich noch einen Schritt weiter und setze die gesamte SQL-Instanz offline, nachdem ich Sicherheit, Jobs, Verbindungsserver, Zertifikate, Datenbank-E-Mail-Einstellungen und andere instanzweite Informationen ausgeführt habe. Dies vermeidet ein Problem beim Testen, bei dem jemand sagt "Alles sieht gut aus!" Nur um ein oder zwei Tage später festzustellen, dass sie mit der alten Datenbank auf dem alten Server gesprochen haben. Indem Sie diese Datenbanken offline schalten oder die gesamte Instanz offline schalten, können Sie diese Fehlalarme und die damit verbundenen Probleme vermeiden.

So beschleunigen Sie den Migrationsansatz

Sie können die für die Umstellung von einer alten auf eine neue Umgebung für eine ausgelastete Produktionsumgebung mit geringen Ausfallzeiten erforderlichen Ausfallzeiten minimieren, indem Sie das vollständige Wiederherstellungsmodell verwenden. Grundsätzlich - bereiten Sie die Umgebung, in die Sie migrieren, auf, indem Sie die neueste vollständige Sicherung, alle differenziellen Sicherungen und alle bereits erstellten Protokollsicherungen unter Angabe NORECOVERYder Daten wiederherstellen. Dann müssen Sie für die endgültige Umstellung nur die Protokollsicherungen wiederherstellen, die noch nicht wiederhergestellt wurden, und Die letzte Log-Sicherung, die Sie wiederherstellen möchten WITH RECOVERY. Auf diese Weise kann bei einer großen Datenbank das tatsächliche Stillstandszeitfenster drastisch minimiert werden, indem die Kosten für die vollständigen, differenziellen und meisten Protokollwiederherstellungen vor dem Stillstandszeitfenster bezahlt werden. Vielen Dank an Tao für den Hinweis in den Kommentaren!

So machen Sie das In-Place-Upgrade sicherer

Einige Dinge, die Sie tun können, um Ihre Erfahrungen und Ergebnisse bei der Auswahl des In-Place-Ansatzes zu verbessern.

  • Backup - Nehmen Sie im Voraus geeignete Backups aller Benutzer- und Systemdatenbanken Ihrer Umgebung vor und stellen Sie sicher, dass diese fehlerfrei sind (ich bin paranoid). Ich würde sie tatsächlich irgendwo zuerst wiederherstellen, um wirklich zu wissen, dass sie fehlerfrei sind. Sie können sich jedoch im Katastrophenfall bedanken. Schreiben Sie Konfigurationsinformationen zur SQL- und Betriebssysteminstallation in dieser Umgebung aus.
  • Testen Sie die Dinge, bevor Sie beginnen - Stellen Sie sicher, dass Sie eine gute Umgebung und gute Datenbanken haben. Sie sollten sich beispielsweise die Fehlerprotokolle ansehen und DBCC CHECKDB regelmäßig ausführen, aber bevor Sie ein direktes Upgrade durchführen, ist ein guter Zeitpunkt, um damit zu beginnen. Beheben Sie Probleme im Voraus.
  • Sicherstellen, dass das Betriebssystem fehlerfrei ist - Stellen Sie nicht nur sicher, dass SQL fehlerfrei ist, sondern auch, dass Ihr Server fehlerfrei ist. Haben Sie schwerwiegende Fehler in Ihren System- oder Anwendungsfehlerereignisprotokollen? Wie ist dein freier Speicherplatz?
  • Bereiten Sie sich auf das Schlimmste vor - ich hatte vor einiger Zeit eine Blog-Post-Serie, die unter der Voraussetzung lief, dass Sie sich tatsächlich auf das Scheitern vorbereiten, wenn Sie sich nicht auf das Scheitern vorbereiten . Ich glaube das immer noch. Überlegen Sie sich also die Probleme, die Sie möglicherweise haben, und setzen Sie sich entsprechend vorab mit ihnen auseinander. Versetzen Sie sich in die Denkweise des "Scheiterns" und Sie werden an Dinge denken, die Sie sonst nicht hätten.

Die Bedeutung von Upgrade- oder Migrationschecklisten

Wenn Sie sich für ein Upgrade entscheiden (ob vorhanden oder migriert), sollten Sie ernsthaft in Betracht ziehen, eine Checkliste zu erstellen und diese Checkliste in jeder Umgebung zu verwenden. Sie sollten eine Reihe von Dingen in diese Checkliste aufnehmen, nicht zuletzt:

  1. Zu Beginn - Führen Sie beispielsweise ein Testupgrade durch, testen Sie Ihre Anwendungen auf der neuesten Datenbankkompatibilitätsstufe und überlegen Sie, ob Sie im Voraus ein Tool wie den SQL Server Upgrade Advisor ausführen, um festzustellen, welche Aufgaben Sie ausführen müssen, bevor Sie SQL ausführen Server Upgrade oder Migration.
  2. Vorbereitende Schritte - Aufräumen, Betriebssystemaufgaben, vorzeitiges Patchen, Vorbereiten von Anwendungen für das Upgrade (sauberes Herunterfahren, Arbeiten mit Verbindungszeichenfolgen), Backups usw.
  3. Upgrade- / Migrationsschritte - Alles, was Sie tun müssen, damit das Upgrade oder die Migration erfolgreich und in der richtigen Reihenfolge durchgeführt werden kann. Änderungen an der Installation, am Kompatibilitätsmodus (oder nicht in Abhängigkeit von Ihren Tests und Vorgehensweisen), an Datenbanken usw.
  4. Schritte nach der Migration / Aktualisierung - Verschiedene Tests, Veröffentlichung einer neuen Version oder neuer Serverkonfigurationsoptionen, Implementierung bewährter Methoden, Sicherheitsänderungen usw.
  5. Rollback-Schritte - Auf dem gesamten Weg sollten Sie Rollback-Schritte und Meilensteine ​​haben. Wenn Sie so weit kommen und dies passiert, was werden Sie dann tun? Was sind die Kriterien für einen vollständigen Rollback? Und wie machen Sie dieses Rollback (Änderungen der Verbindungszeichenfolge rückgängig machen, Einstellungen rückgängig machen, zur alten Version zurückkehren, neu installieren, falls vorhanden, bei einer Migration auf den alten Server verweisen, usw.)

Lassen Sie dann die Person, die die Produktionsaktualisierung vornimmt, die Checkliste in einer anderen Umgebung als der Produktion befolgen - insbesondere in einer Umgebung, in der das Schließen möglichst der Produktion ähnelt ("South of Prod", wie ich sage ...), und notieren Sie sich alle Probleme oder Punkte wo sie von der Checkliste ablenken oder wegen eines Mangels an der Checkliste improvisieren mussten. Dann lassen Sie die Änderungen einfließen und haben Spaß mit Ihrer Produktionsänderung.

Ich kann nicht genug betonen, wie wichtig es ist, nach der Migration oder dem Upgrade gründliche Tests durchzuführen, bevor Sie mit der Migration beginnen. Eine Rollback-Entscheidung während eines Upgrades sollte einfach sein - insbesondere während einer Migration. Wenn es etwas Unangenehmes gibt, führen Sie ein Rollback durch und finden Sie es heraus, wenn Sie es in der Hitze der Migration nicht effektiv und zuverlässig beheben können. Sobald Sie mit dieser neuen Umgebung vertraut sind und Benutzer eine Verbindung herstellen, wird das Rollback zu einer schwierigen Aufgabe. Sie können eine SQL Server-Datenbank nicht auf eine frühere Version zurücksetzen. Das bedeutet manuelle Arbeit und Datenmigrationen. Ich warte immer ein paar Wochen, um die alte Umgebung zu töten, aber Sie sollten alles tun, um zu vermeiden, dass diese alte Umgebung benötigt wird, indem Sie alle Ihre Probleme finden, bevor Ihre Live-Benutzer jemals die neue Umgebung berühren. Am besten, bevor Sie mit dem Upgrade / der Migration beginnen.

Kurzer Hinweis zur Migration / Aktualisierung von SQL Server Reporting Services Die Migration einer SSRS-Installation ist keine herkulische Aufgabe, wie viele meinen. Dieser Technet / Books Online-Artikel ist eigentlich ganz praktisch . Eine der wichtigsten Warnungen in diesem Artikel lautet "Sichern der Verschlüsselungsschlüssel", insbesondere wenn Sie viele vertrauliche Informationen wie geplante E-Mail-Adressen von Berichtsempfängern, Verbindungsinformationen für eine Vielzahl von Verbindungen usw. gespeichert haben Ich kann einen meiner Kunden schon seit einiger Zeit fragen, wie wichtig das ist. Sie wissen es, weil ich diesen Schritt durcheinander gebracht und ziemlich viel Zeit damit verbracht habe, Berichtszeitpläne und Berechtigungen für Verbindungszeichenfolgen zu ändern.

Mike Walsh
quelle
14

Meiner Erfahrung nach sollte derselbe Entscheidungsprozess wie zuvor durchgeführt werden. AFAIK Bei der Installation von SQL Server im MS SQL Server-Produkt selbst und den potenziellen Problemen, die bei der Einführung von Software mit Millionen von Codezeilen auftreten können, gab es keine "Weltveränderer". Es könnte etwas Schlimmes passieren, und jetzt haben Sie keine ROLLBACK-Option mehr.

Sie haben jedoch andere Alternativen. Sie können einen Snapshot des Systems erstellen, an einer anderen Stelle wiederherstellen, das Upgrade durchführen und sehen, was passiert. Dieser Test sollte Ihnen viel Komfort bieten, garantiert jedoch nicht, dass keine Probleme mit der Prod Box auftreten. Dies ist jedoch eine Option, die in SQL 6.5-Tagen nicht verfügbar war.

Ich würde nur den schlimmsten Fall annehmen. Sie führen ein direktes Upgrade durch und es schlägt kläglich fehl. Sie müssen sich dann in Ihrem RTO und RCO davon erholen. Versteht das Unternehmen die Risiken und haben Sie Pläne, diese zu mindern?

Wenn das Geschäft damit nicht in Ordnung ist, dann tue es nicht, wäre mein Rat.

Ali Razeghi
quelle
2

Wenn Ihre Server in einer virtuellen Umgebung ausgeführt werden, können Sie einen Snapshot für einen Klon ausführen und dann das direkte Upgrade anwenden und die Instanz testen, um sicherzustellen, dass das Upgrade erfolgreich war. Wenn dies funktioniert, können Sie den Snapshot anwenden und den Klon zum Produktionsserver machen. Wenn dies nicht funktioniert, können Sie den Snapshot löschen und zum Image vor dem Upgrade zurückkehren, um es erneut zu versuchen, oder den Klon löschen und eine vollständige Migration durchführen.

Troy
quelle
1
Nur wenn der Speicher auch virtualisiert und Teil des Snapshots ist. Wenn der Speicher direkt mit der VM verbunden ist, wird beim Wiederherstellen des Snapshots kein '
Rollback
1

Aufgrund einer großen Hardware-Investition mussten wir nur das Betriebssystem aktualisieren und dabei die aktuelle SQL Server-Version (2012, 3 Server, 22 Instanzen, ~ 300 Datenbanken) beibehalten. Keine komplexen Einstellungen wie Spiegeln usw.

Dieses Beispiel stimmt nicht genau mit der Frage überein, da SQL Server nicht aktualisiert wird. Ich denke, dies ist immer noch eine gute Antwort, da die gezeigten Schritte tatsächlich einfacher wären als eine echte In-Place-Migration.

Übersicht: Ein externes Laufwerk wurde angeschlossen, um vor allem vorsorglich vollständige Sicherungen durchzuführen. Nur das Modell und msdb werden tatsächlich vom externen Laufwerk wiederhergestellt. Die ldf / mdf wurden zum Abnehmen / Anbringen an Ort und Stelle belassen. Einige lokale Konten wurden in den DBs referenziert. Nachdem sie im Betriebssystem neu erstellt wurden, wurden die Verweise in der Datenbank neu erstellt (da sich die SIDs möglicherweise ändern).

Dann waren hier die Schritte, die für uns gearbeitet haben:

1) Notieren Sie sich die Einstellungen auf Serverebene, die in den Schritten 12 (Serverrollen) und 18 bis 23 wiederhergestellt werden.

2) Patchen Sie SQL Server 2012 auf SP3 (Konsistenz erforderlich, wenn Sie System-DBs wiederherstellen möchten).

3) Stellen Sie sicher, dass die Versionen für jede Instanz übereinstimmen. "Version auswählen"

4) Erstellen Sie diese 6 Skripte, indem Sie dieses Skript ausführen. Redgate SQL Multiscript ist eine enorme Zeitersparnis, wenn es viele Instanzen gibt (Passen Sie die Werkzeuge -> Optionen => Zeilenlänge auf das Maximum an (8192) und verwenden Sie dann die Textausgabe).

  • Backup
  • Wiederherstellen
  • Ablösen
  • Anfügen
  • Logins neu erstellen
  • Benutzer erneut mit Anmeldungen verknüpfen

    -- (1) BACKUP / (2) RESTORE
    --    
    --*** SET THESE to external drive location
    --*** and create the Destination Directories
    declare 
        @backupInstanceDir  varchar(300) = 'F:\ExternalDriveBackups\' + replace(@@servername, '\', '_'),
        @dateSuffix         varchar(100) = '2015-12-14'; 
    
    if (object_id('tempdb..DatabaseStatus') is not null)
    drop table #DAtabseSTatus;
    
    select 
        d.name DbName, 
        d.state_desc DbState,
        d.user_access_desc UserMode,
        convert(bit, (d.is_read_only * -1 + 1)) as IsWritable,
        d.is_trustworthy_on as IsTrustWorthy,
        d.is_in_standby IsInStandby,
        d.recovery_model_desc RecoveryModel,
        suser_sname(d.owner_sid) as Owner,
        convert(bit, 
            case when d.database_id <= 4 or d.is_distributor = 1
                then 1
                else 0
            end) as IsSystemDb,
        mf.type_desc as FileType,
        mf.name FileName,
        mf.state FileState,
        mf.state_desc FileStatDesc,
        mf.physical_name PhysicalName,
        mf.type as FileTypeId    
    into #DatabaseStatus
    from
        sys.master_files AS mf
    join sys.databases AS d
    ON  mf.database_id = d.database_id
    where
        1=1
    order by
        d.name,
        mf.physical_name;
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutBU
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutRE
    
    create table #sqlOutBU
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    create table #sqlOutRE
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutBU select char(10) + '-- BACKUP SCRIPT' + char(10);
    insert into #sqlOutRE select char(10) + '-- RESTORE SCRIPT' + char(10);
    
    
    insert into #sqlOutBU select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOutRE select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';        
    
    PRINT '--Script for Backing up all DBs in a SQL Server Instance to a specific location' 
    
    SET nocount ON 
    
    insert into #sqlOutBU select char(10) + 
    '--' + char(10) + '-- BACKUP ' + @@servername + '--' + char(10) + 
    'use [Master]; set deadlock_priority high;' + char(10);
    
    insert into #sqlOutRE select '
    -- RESTORE
    --
    -- BE SURE TO BACKUP SYSTEM DBS TO AN ALTERNATE LOCATION JUST BEFORE RESTORING!
    --
    use [Master]; set deadlock_priority high;' + char(10);
    
    DECLARE @dbname nvarchar(128) 
    declare dblist_cursor cursor fast_forward for 
    select [name] from master.sys.databases where [name] != 'tempdb'
    order by iif(database_id <= 4, '0', '1') + [name]
    
    open dblist_cursor 
    fetch next from dblist_cursor into @dbname 
    
    while @@fetch_status = 0 
    begin 
    
        declare @bak nvarchar(300) = @backupInstanceDir + '\' + @dbname + '_' + @dateSuffix + '.bak';
    
        insert into #sqlOutBU select char(10) + 'backup database [' + @dbname + '] to disk = ''' + @bak + ''' WITH COPY_ONLY, NOFORMAT, NOINIT, ' + char(10) + 
            'NAME = N''' + @dbName + '-Full'', SKIP, NOREWIND, NOUNLOAD, COMPRESSION, STATS = 25;';
    
        insert into #sqlOutRE select 'restore database [' + @dbName + '] from disk = ''' + @bak + ''' WITH FILE = 1,' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Rows' and DbName = @dbName
        ) + ',' + char(10) +
        (
            select '    move ''' + FileName + ''' to ''' + PhysicalName + '''' From #DatabaseStatus
            where FileType = 'Log' and DbName = @dbName
        ) + ',' + char(10) +
        '    NOUNLOAD, REPLACE, STATS = 25;' + char(10);               
    
        fetch next from dblist_cursor into @dbname 
    end 
    
    close dblist_cursor 
    deallocate dblist_cursor 
    
    insert into #sqlOutBU select char(10) + 'go' + char(10);
    insert into #sqlOutRE select char(10) + 'go' + char(10);
    
    select Command from #sqlOutBU order by Row; -- BACKUP SCRIPT
    select Command from #sqlOutRE order by Row; -- RESTORE SCRIPT
    
    go
    
    
    
    --
    -- (3) DETACH  -  Org Author: Artemakis Artemiou
    --      
    
    if object_id('tempdb..#sqlOutDT') is not null
        drop table #sqlOutDT
    
    create table #sqlOutDT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutDT select char(10) + '-- DETACH all DBs from a SQL Server Instance' + char(10);      
    
    insert into #sqlOutDT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET nocount ON 
    
    insert into #sqlOutDT select char(10) + '--' + char(10) + '-- DETACH ' + @@servername + char(10) + '--' + char(10) + '
    use MAster; set deadlock_priority high;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128) 
    DECLARE dblist_cursor CURSOR fast_forward FOR 
    SELECT [name] 
    FROM   master.sys.databases 
    WHERE  database_id > 4 
    
    OPEN dblist_cursor 
    FETCH next FROM dblist_cursor INTO @dbname 
    
    WHILE @@FETCH_STATUS = 0 
    BEGIN 
        insert into #sqlOutDT select
        'alter database ' + @dbname + ' set single_user with rollback immediate;' + char(10) +
        'EXEC sp_detach_db ''' + @dbname + ''', ''true'';' + char(10);
        FETCH next FROM dblist_cursor INTO @dbname 
    END 
    
    CLOSE dblist_cursor 
    DEALLOCATE dblist_cursor 
    
    insert into #sqlOutDT select char(10) + 'go' + char(10);
    select Command from #sqlOutDT order by Row;
    
    go
    
    
    
    --
    -- (4) ATTACH  -  Org Author: Artemakis Artemiou
    --    
    
    if object_id('tempdb..#sqlOut') is not null
        drop table #sqlOutAT
    
    create table #sqlOutAT
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOutAT select char(10) + '-- ATTACH ALL DBs to a SQL Server Instance' + char(10);
    
    insert into #sqlOutAT select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    SET NOCOUNT ON
    
    insert into #sqlOutAT select char(10) + '--' + char(10) + '-- ATTACH ' + @@servername + char(10) + '--' + char(10) + 
    'use MAster;' + char(10) + char(10);
    
    DECLARE @dbname nvarchar(128);
    
    DECLARE DBList_cursor CURSOR fast_forward FOR 
    select [name] from master.sys.databases where database_id > 4
    order by name;
    
    OPEN DBList_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    WHILE @@FETCH_STATUS = 0
    BEGIN
    
    declare @attach_TSQL_script varchar(max)
    set @attach_TSQL_script=''
    set @attach_TSQL_script=@attach_TSQL_script+'CREATE DATABASE ' + @dbname +' ON ' 
    
    declare @tsql varchar(max),@filename varchar(max)
    set @tsql='DECLARE DBFiles_cursor CURSOR FOR select [filename] from '+ @dbname + '.sys.sysfiles'
    
    execute (@tsql) 
    
    PRINT '--'+@dbname 
    
    OPEN DBFiles_cursor
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    
    WHILE @@FETCH_STATUS = 0
    BEGIN   
    set @attach_TSQL_script=@attach_TSQL_script+ char(10)+'    (FILENAME = '''+ @filename +'''),' 
    FETCH NEXT FROM DBFiles_cursor INTO @filename
    END
    
    set @attach_TSQL_script=SUBSTRING(@attach_TSQL_script,0,len(@attach_TSQL_script))
    set @attach_TSQL_script=@attach_TSQL_script+ char(10) +'    FOR ATTACH;';
    
    insert into #sqlOutAT select @attach_TSQL_script + char(10);
    
    PRINT @attach_TSQL_script 
    PRINT ''
    
    CLOSE DBFiles_cursor
    DEALLOCATE DBFiles_cursor
    
    FETCH NEXT FROM DBList_cursor 
    INTO @dbname
    
    END 
    
    CLOSE DBList_cursor
    DEALLOCATE DBList_cursor
    
    insert into #sqlOutAT select char(10) + 'go' + char(10);
    select Command from #sqlOutAT order by Row;
    go
    
    
    
    --
    -- (5) GENERATE A 'RE-CREATE LOGINS' SCRIPT
    --
    -- This script was modified from a version that was designed to copy from one server to another:
    --      http://stackoverflow.com/a/5983773/538763
    --
    
    
    USE [master]
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
    Command nvarchar(max) not null,
    Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RECREATE LOGINS' + char(10);
    
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    insert into #sqlOut select 'use Master;' + char(10);
    go
    SET ANSI_NULLS ON
    GO
    SET QUOTED_IDENTIFIER ON
    GO
    declare @Debug bit = 0;
    declare @PartnerServer varchar(100) = @@SERVICENAME;  -- use current server before it is shutdown (disabled below)
    
    declare
        @MaxID int,
        @CurrID int,
        @SQL nvarchar(max),
        @LoginName sysname,
        @IsDisabled int,
        @Type char(1),
        @SID varbinary(85),
        @SIDString nvarchar(100),
        @PasswordHash varbinary(256),
        @PasswordHashString nvarchar(300),
        @RoleName sysname,
        @Machine sysname,
        @PermState nvarchar(60),
        @PermName sysname,
        @Class tinyint,
        @MajorID int,
        @ErrNumber int,
        @ErrSeverity int,
        @ErrState int,
        @ErrProcedure sysname,
        @ErrLine int,
        @ErrMsg nvarchar(2048);
    
    declare @Logins Table (LoginID int identity(1, 1) not null primary key,
                        [Name] sysname not null,
                        [SID] varbinary(85) not null,
                        IsDisabled int not null,
                        [Type] char(1) not null,
                        PasswordHash varbinary(256) null)
    declare @Roles Table (RoleID int identity(1, 1) not null primary key,
                    RoleName sysname not null,
                    LoginName sysname not null)
    declare @Perms Table (PermID int identity(1, 1) not null primary key,
                    LoginName sysname not null,
                    PermState nvarchar(60) not null,
                    PermName sysname not null,
                    Class tinyint not null,
                    ClassDesc nvarchar(60) not null,
                    MajorID int not null,
                    SubLoginName sysname null,
                    SubEndPointName sysname null)
    
    Set NoCount On;
    
    If CharIndex('\', @PartnerServer) > 0
    Begin
    Set @Machine = LEFT(@PartnerServer, CharIndex('\', @PartnerServer) - 1);
    End
    Else
    Begin
    Set @Machine = @PartnerServer;
    End
    
    -- Get all Windows logins from principal server
    Set @SQL = 'Select P.name, P.sid, P.is_disabled, P.type, L.password_hash' + CHAR(10) +
        'From ' /*+ QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals P' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.sql_logins L On L.principal_id = P.principal_id' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'and P.Name Not like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;';
    
    Insert Into @Logins (Name, SID, IsDisabled, Type, PasswordHash)
    Exec sp_executesql @SQL;
    
    -- Get all roles from principal server
    Set @SQL = 'Select RoleP.name, LoginP.name' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_role_members RM' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + .*/ +'master.sys.server_principals RoleP' +
        CHAR(10) + char(9) + 'On RoleP.principal_id = RM.role_principal_id' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + 'master.sys.server_principals LoginP' +
        CHAR(10) + char(9) + 'On LoginP.principal_id = RM.member_principal_id' + CHAR(10) +
        'Where LoginP.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And LoginP.name <> ''sa''' + CHAR(10) +
        'And LoginP.name Not Like ''##%''' + CHAR(10) +
        'And LoginP.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And RoleP.type = ''R''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', LoginP.name) = 0;';
    
    Insert Into @Roles (RoleName, LoginName)
    Exec sp_executesql @SQL;
    
    -- Get all explicitly granted permissions
    Set @SQL = 'Select P.name Collate database_default,' + CHAR(10) +
        '   SP.state_desc, SP.permission_name, SP.class, SP.class_desc, SP.major_id,' + CHAR(10) +
        '   SubP.name Collate database_default,' + CHAR(10) +
        '   SubEP.name Collate database_default' + CHAR(10) +
        'From '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals P' + CHAR(10) +
        'Inner Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_permissions SP' + CHAR(10) +
        CHAR(9) + 'On SP.grantee_principal_id = P.principal_id' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.server_principals SubP' + CHAR(10) +
        CHAR(9) + 'On SubP.principal_id = SP.major_id And SP.class = 101' + CHAR(10) +
        'Left Join '/* + QUOTENAME(@PartnerServer) + '.*/ + ' master.sys.endpoints SubEP' + CHAR(10) +
        CHAR(9) + 'On SubEP.endpoint_id = SP.major_id And SP.class = 105' + CHAR(10) +
        'Where P.type In (''U'', ''G'', ''S'')' + CHAR(10) +
        'And P.name <> ''sa''' + CHAR(10) +
        'And P.name Not Like ''##%''' + CHAR(10) +
        'And P.name Not Like ''NT SERVICE%''' + CHAR(10) +
        'And CharIndex(''' + @Machine + '\'', P.name) = 0;'
    
    Insert Into @Perms (LoginName, PermState, PermName, Class, ClassDesc, MajorID, SubLoginName, SubEndPointName)
    Exec sp_executesql @SQL;
    
    --select * from @Logins;
    --select * from @Roles;
    --select * from @perms;
    
    
    Select @MaxID = Max(LoginID), @CurrID = 1
    From @Logins;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = Name,
        @IsDisabled = IsDisabled,
        @Type = [Type],
        @SID = [SID],
        @PasswordHash = PasswordHash
    From @Logins
    Where LoginID = @CurrID;
    
    --    If Not Exists (Select 1 From sys.server_principals
    --              Where name = @LoginName)
    Begin
    
        set @sql = char(10);
        set @sql += 'If Not Exists (Select 1 From sys.server_principals Where name = ''' + @LoginName + ''')' + char(10);
        set @sql += 'begin' + char(10) + '    ';
    
        Set @SQL += 'Create Login ' + quotename(@LoginName)
        If @Type In ('U', 'G')
        Begin
            Set @SQL = @SQL + ' From Windows;'
        End
        Else
        Begin
            Set @PasswordHashString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@PasswordHash"))', 'nvarchar(300)');
    
            Set @SQL = @SQL + ' With Password = ' + @PasswordHashString + ' HASHED;  --, ';
    
            Set @SIDString = '0x' +
                Cast('' As XML).value('xs:hexBinary(sql:variable("@SID"))', 'nvarchar(100)');
            Set @SQL = @SQL + 'SID = ' + @SIDString + ';' + char(10);
        End
    
        set @sql += char(10) +
            '    print ''Created Login ' + @loginName  + ''';' + char(10) +
            'end' + char(10) +
            'else' + char(10) +
            convert(nvarchar(max), '    print ''Login ' + @loginName + ' already existed. '';') + char(10);
    
        If @Debug = 0
        insert into #sqlOut select @SQL;                      
        Else
        Print @SQL;
    
        If @IsDisabled = 1
        Begin
            Set @SQL = 'Alter Login ' + quotename(@LoginName) + ' Disable;'
            If @Debug = 0
                insert into #sqlOut select @SQL;                              
            Else              
                Print @SQL;              
        End
        End
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    Select @MaxID = Max(RoleID), @CurrID = 1
    From @Roles;
    
    While @CurrID <= @MaxID
    Begin
    Select @LoginName = LoginName,
        @RoleName = RoleName
    From @Roles
    Where RoleID = @CurrID;
    
    /*  If Not Exists (Select 1 From sys.server_role_members RM
                Inner Join sys.server_principals RoleP
                    On RoleP.principal_id = RM.role_principal_id
                Inner Join sys.server_principals LoginP
                    On LoginP.principal_id = RM.member_principal_id
                Where LoginP.type In ('U', 'G', 'S')
                And RoleP.type = 'R'
                And RoleP.name = @RoleName
                And LoginP.name = @LoginName)*/
    Begin
        If @Debug = 0
        Begin          
            insert into #sqlOut select 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''', @loginame = ''' + @LoginName + ''';';
        End
        Else
        Begin
            Print 'Exec sp_addsrvrolemember @rolename = ''' + @RoleName + ''',';
            Print '     @loginame = ''' + @LoginName + ''';';
        End
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    insert into #sqlOut select char(10) + 'use Master;' + char(10);
    
    
    Select @MaxID = Max(PermID), @CurrID = 1
    From @Perms;
    
    While @CurrID <= @MaxID
    Begin
    Select @PermState = PermState,
        @PermName = PermName,
        @Class = Class,
        @LoginName = LoginName,
        @MajorID = MajorID,
        @SQL = PermState + space(1) + PermName + SPACE(1) +
            Case Class When 101 Then 'On Login::' + QUOTENAME(SubLoginName)
                    When 105 Then 'On ' + ClassDesc + '::' + QUOTENAME(SubEndPointName)
                    Else '' End +
            ' To ' + QUOTENAME(LoginName) + ';'
    From @Perms
    Where PermID = @CurrID;
    
    /*If Not Exists (Select 1 From sys.server_principals P
                Inner Join sys.server_permissions SP On SP.grantee_principal_id = P.principal_id
                Where SP.state_desc = @PermState
                And SP.permission_name = @PermName
                And SP.class = @Class
                And P.name = @LoginName
                And SP.major_id = @MajorID)*/
    Begin
        If @Debug = 0
                insert into #sqlOut select @sql;                      
        Else          
            Print @SQL;          
    End
    
    Set @CurrID = @CurrID + 1;
    End
    
    
    select Command from #sqlOut as SqlOut order by Row;
    go
    
    
    --
    -- (6) Generate a script to Re-link all users to logins based on current state (before shutdown)
    --
    
    use Master;
    
    if object_id('tempdb..#sqlOut') is not null
    drop table #sqlOut;
    
    create table #sqlOut
    (
        Command nvarchar(max) not null,
        Row int identity(1,1) not null primary key
    );
    
    insert into #sqlOut select char(10) + '-- RELINK USERS TO LOGINS' + char(10);
    
    insert into #sqlOut select char(10) + char(10) + '/* ---------------------------------------------------------------------------------------------' + char(10) + 
    'ServerName: ' + @@servername + char(10) + 'ServiceName: ' + @@servicename + char(10) + 'Version: ' + @@version + 
    '--------------------------------------------------------------------------------------------- */';
    
    declare @dbCmd varchar(8000) = '
    use ?;
    
    insert into #sqlOut select char(10) + ''use ?;'' + char(10);  
    
    with links as
    (
    select u.name as UserName,
        l.loginname as LoginName
        from sysusers u 
        join master..syslogins l
        on u.sid = l.sid        
    where u.name != ''dbo''
        and u.isSqlUser = 1 or l.isNtName = 1 or l.isNtGroup = 1
    )
    insert into #sqlOut 
    select ''alter user ['' + UserName + ''] with name = ['' + UserName + ''], login = ['' + LoginName + '']''
    from links
    ';    
    
    exec sp_MSforeachdb @dbCmd;
    
    select Command from #sqlOut order by Row;
    
    go

5) Führen Sie ein Skript aus, um alle DBs einschließlich des Systems (Master, MSDB, Modell) auf einem externen Laufwerk zu sichern.

6) Führen Sie ein Skript aus, um alle DBs zu trennen

7) C Das Laufwerk wird neu formatiert. Bewahren Sie die LDF / MDFs auf, wenn sie NICHT auf C waren.

8) Windows Server 2012 ist auf C installiert

9) Verschieben Sie den LDF / MDF für die ursprünglichen Systemdateien aus dem Weg, wenn sie nicht auf dem Laufwerk C gespeichert waren.

10) SQL Server 2012 wird neu installiert und auf SP3 gepatcht. A. Erstellen Sie die Systembenutzer- / Gruppenkonten neu

11) Sichern Sie die System-DBs an einen NEUEN Speicherort oder Dateinamen (achten Sie darauf, die Originale nicht zu überschreiben!).

12) Führen Sie das Snippet zum erneuten Erstellen von Rollen aus. So etwas wie:

USE [master]
CREATE SERVER ROLE [SomeServerRole]
--ALTER SERVER ROLE [dbcreator] ADD MEMBER [SomeServerRole]
--ALTER SERVER ROLE [bulkadmin] ADD MEMBER [SomeServerRole]
-- ALTER SERVER ROLE [SomeServerRole] ADD MEMBER [SomeMemberOrRole]

13) Führen Sie das Skript zum erneuten Erstellen der Anmeldung aus (führt keine Aktionen aus, wenn die Anmeldungen wiederhergestellt wurden).

14) Beenden Sie SQL AGENT.

(Könnte den Meister hier wiederherstellen, wir sind durchgeknallt).

15) Fügen Sie mdf / ldf mithilfe des obigen Skripts hinzu. ein. Wenn dies fehlschlägt, stellen Sie es manuell mithilfe des obigen Skripts wieder her.

16) Versuchen Sie, das Modell wiederherzustellen

17) Stellen Sie sicher, dass SQL Agent gestoppt ist. Wiederherstellen der MSDB (Link) a. Wenn dies fehlschlägt, müssen Jobs + Wartungsplan + E-Mail-Konfiguration + Bediener neu erstellt werden

18) Benutzer öffnen, um sich einzuloggen ...

    a. If there are master users (rare?) then First Re-Create users for master since it was not restored:
        use master;       
        CREATE USER [ABC] FOR LOGIN [machine\ABC]

    b. Run the rest of the script

19) Aktivieren Sie den Service Broker für die Übereinstimmung mit dem ursprünglichen Wert SELECT name, is_broker_enabled FROM sys.databases.

    alter database MSDB set single_user with rollback immediate;
    ALTER DATABASE [MSDB] SET ENABLE_BROKER;
    alter database MSDB set multi_user;

20) Starten Sie SQL Agent

21) Setzen Sie die Parallelitätsschwelle auf den ursprünglichen Wert

22) Passen Sie alle Datenbankeinstellungen an ihre ursprünglichen Werte an:

 declare @dbCmd varchar(8000) = '
      use ?;
      if db_name() not in (''master'', ''model'', ''tempdb'', ''msdb'')
      begin
             print ''Adjusting [?]...'';    
            alter database [?] set single_user with rollback immediate;
             aLTER AUTHORIZATION ON DATABASE::[?] to [sa];
            -- alter database [?] set trustworthy on;
            ALTER DATABASE [?] SET AUTO_CLOSE OFF WITH NO_WAIT;     
            alter database [?] set multi_user;
      end     
      else
             print ''Skipping [?]...'';
    ';    

    exec sp_MSforeachdb @dbCmd;

23) Überprüfen Sie den Jobbesitz:

select s.name as JobName, l.name as login, SUSER_SNAME(s.owner_sid) AS login2
from  msdb..sysjobs s 
left join master.sys.syslogins l on s.owner_sid = l.sid

Wenn auch die SQL Server-Version aktualisiert worden wäre, glaube ich nicht, dass die Modell- und MSDB-Datenbanken wiederhergestellt werden könnten, sodass Jobs aufgrund von https://support.microsoft.com/en-us/kb/264474 verloren gegangen wären

Was fehlt:

  • Ursprüngliche Benutzer in der Master-Datenbank (selten?)
  • Serverrollen
  • ?
crokusek
quelle
0

An beiden Ansätzen ist nichts auszusetzen - ich habe beides getan, und beide Ergebnisse sind in der Regel gut.

Wenn es ein Problem mit dem Migrationsansatz gibt, handelt es sich nicht um ein technisches Problem, sondern um Faulheit. Zu oft stelle ich fest, dass ein Unternehmen noch nicht vollständig auf die xxxx-Version umgestiegen ist, weil es sich für eine Swing-Migration entschieden hat und nie die harte Arbeit geleistet hat, sich vollständig zu bewegen. Jetzt haben sie zwei oder mehr Sätze von Servern anstelle von einem.

RowlandG
quelle