Zunächst einmal vielen Dank, dass Sie sich das angesehen haben. Wir haben eine große Datenbank in unserer Produktionsumgebung (1,26 TB), die einige hundert beschädigte Seiten enthält und seit Monaten funktioniert, sodass insgesamt dieselbe Korruption vorliegt der verfügbaren Backups.
Ich wurde in diese späte letzte Woche hineingezogen, da die geplanten Jobs für die Reorganisation von Indizes anscheinend seit einiger Zeit aufgrund der Korruption fehlgeschlagen sind und wir uns jetzt in einem Stadium befinden, in dem die Indizes für die größten und am häufigsten verwendeten Tabellen zwischen 50% und 50% liegen 80% Fragmentierung, die die Anwendungsleistung ernsthaft beeinträchtigt.
Ich habe eine Reihe von Ideen gehabt, wie ich diese Situation beheben könnte (glauben Sie mir, ich bin mehr als offen für Alternativen), und nach dem, was ich gelesen habe, halte ich Folgendes für eine gute Idee:
- Erstellen Sie eine komprimierte Sicherung der beschädigten Datenbank aus der Produktion (SQL Server 2008R2), kopieren Sie sie auf unseren (lokalen) Entwicklungsserver (SQL Server 2016) und führen Sie die Reparatur aus (auf dem Produktionssystem ist nicht genügend Speicherplatz für zwei Kopien vorhanden) die beschädigte Datenbank gleichzeitig angehängt).
- Stellen Sie zwei Kopien dieser beschädigten Sicherung auf dem Entwicklungsserver wieder her, auf dem genügend Speicherplatz vorhanden ist.
- Führen Sie die Reparatur auf dem Entwicklungsserver mit der Option allow_data_loss für eine dieser Datenbank aus und benennen Sie sie in "DbNameHereRepaired" um (bei den meisten beschädigten Seiten, die ich mit DBCC PAGE angesehen habe, waren die Daten ohnehin auf 0x00 gesetzt).
Benennen Sie eine andere Kopie in DbNameHereCorrupt um und versuchen Sie, die Wiederherstellung auf Seitenebene mit dem folgenden Code auszuführen:
alter database DbNameHereCorrupt set single_user with rollback immediate --set db to FULL recovery mode alter database DbNameHereCorrupt set recovery full --Declare paths for backups declare @fullBackupPath nvarchar(max) = N'D:\Restore\DbNameHereCorrupt-FullBackup.bck' declare @tranLogBackupPath nvarchar(max) = N'D:\Restore\DbNameHereCorrupt-LogBackup.bck' --Take full backup to begin new TLogChain backup database DbNameHereCorrupt to disk = @fullBackupPath with init, differential; --Immediately after whilst in single user mode, begin the t-log chain, this will also put the db in a restoring state backup log DbNameHereCorrupt to disk=@tranLogBackupPath with init, norecovery; --get corrupted pages declare @corruptedPages nvarchar(max) = ( select stuff ( ( select ',' + cast(s.file_id as nvarchar(20)) + ':' + cast(s.page_id as nvarchar(20)) from msdb.dbo.suspect_pages s where s.database_id = 20 for xml path('') ), 1 ,1, '' ) ) --push page-level restore restore database DbNameHereCorrupt page=@corruptedPages from disk=N'D:\Restore\DbNameHereRepaired.bak' with norecovery; -- restore log over db restore log DbNameHereCorrupt from disk=@tranLogBackupPath with norecovery; -- put db back into usable state restore database DbNameHereCorrupt with recovery --set db to SIMPLE recovery mode alter database DbNameHereCorrupt set recovery simple alter database DbNameHereCorrupt set multi_user
Dies scheint so zu funktionieren, wie ich denke, dass es bis zur Wiederherstellungsanweisung auf Seitenebene funktionieren soll, wo es Fehler gibt, zu sagen:
Meldung 4346, Ebene 16, Status 1, Zeile 35 RESTORE PAGE ist bei Datenbanken, die das einfache Wiederherstellungsmodell verwenden oder die Protokollsicherungskette unterbrochen haben, nicht zulässig.
Dies ist mein erstes Mal, dass ich das vollständige Wiederherstellungsmodell verwende, also habe ich wahrscheinlich etwas falsch gemacht ... Ich kann sehen, wie eine kleine Lücke zwischen dem letzten lsn des Differentials und der Transaktionssicherung aussieht, was ich dort vermute sollte nicht sein.
Kann jemand sehen, was ich hier falsch gemacht habe? Ich habe versucht, Beispielen im Web zu folgen, die alle einem ähnlichen Muster zu folgen scheinen, aber ich denke, ich vermisse etwas?