Inkonsistente Seiten in der Datenbank reparieren

8

Wir haben eine SQL 2000-Datenbank. Der Server stürzte aufgrund eines Raid-Array-Fehlers ab. Wenn wir jetzt DBCC CHECKDB ausführen, erhalten wir den Fehler, dass auf 9 Seiten 27 Konsistenzfehler vorliegen.

Wenn wir DBCC PAGE auf diesen Seiten ausführen, erhalten wir Folgendes:

Msg 8939, Level 16, State 106, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (m_freeCnt == freeCnt) failed. Values are 2 and 19.
Msg 8939, Level 16, State 108, Line 1
Table error: Object ID 1397580017, index ID 2, page (1:8404521). Test (emptySlotCnt == 0) failed. Values are 1 and 0.

Da der angegebene Index nicht geclustert ist und von einer eindeutigen Konstante erstellt wird, die zwei Spalten enthält, haben wir versucht, den Index zu löschen und neu zu erstellen. Dies führte zu folgendem Fehler:

CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 2. Most significant primary key is '3280'. 
The statement has been terminated. 

Jedoch läuft

Select var_id,result_on
from tests
group by var_id,result_on
having count(*)>1

Gibt 0 Zeilen zurück.

Folgendes planen wir:

  • Stellen Sie eine Pre-Server-Absturzkopie der Datenbank wieder her und führen Sie DBCC CHECKDB aus
  • Wenn dies sauber zurückgibt, stellen Sie die Wiederherstellung ohne Wiederherstellung wieder her
  • Wenden Sie alle nachfolgenden TLOG-Sicherungen an
  • Stoppen Sie die Produktions-App, erstellen Sie eine Endprotokoll-Sicherung und wenden Sie diese ebenfalls an
  • Löschen Sie die Produktdatenbank und benennen Sie die frisch wiederhergestellte Datenbank um, damit sie erstellt wird
  • Starten Sie die Produkt-App

Könnte jemand bitte Löcher in diesen Ansatz schlagen? Vielleicht einen anderen Ansatz vorschlagen? Was wir brauchen, ist minimale Ausfallzeit.

SQL 2000 DB Größe 94 GB Die Tabelle mit beschädigten Seiten enthält mehr als 460 Millionen Datenzeilen

Danke für die Hilfe.

Raj


quelle
1
Ich mag deinen Ansatz. Für mich ergibt das Sinn. Vielleicht behalten Sie die beschädigte Datenbank neben sich, als Versicherung ...
user24161
Wenn sich die Dinge beruhigen, planen Sie auch Ihr Upgrade 2008 oder 2008 :-)
user24161
(
dh
+1 für einen gültigen und sehr geeigneten Wiederherstellungsplan
Andrew

Antworten:

2

Ihre Wiederherstellungslösung ist die Lehrbuchmethode, um fortzufahren. Angenommen, Sie verfügen über geeignete Sicherungen und können das Transaktionsprotokoll für die beschädigte Datenbank sichern, dann ist Ihre Strategie das zu implementierende Lehrbuch.

Haben Sie jedoch vor dem Fortfahren die Möglichkeit in Betracht gezogen, nur die betroffene Tabelle neu zu erstellen?

Manchmal können Sie eine exakte Kopie der betroffenen Tabelle erstellen, indem Sie a ausführen

select *
into NewTableFromOld
from DamagedTable

Löschen Sie dann einfach die beschädigte Tabelle und tauschen Sie sie gegen die neue aus. Denken Sie daran, entsprechende Einschränkungen und Indizes hinzuzufügen.

John Sansom
quelle
Danke für die Antwort. Ihr Ansatz sieht gut aus, aber die Sorge ist, dass die Tabelle 461 Millionen Datenzeilen enthält. Welche Auswirkungen hätte dies auf die Produktion, wenn ich eine Auswahl * durchführe? Würde das nicht ein Schloss bekommen und die Leistung beeinträchtigen?
Nicht, wenn Sie den Abfragehinweis mit (nolock) Nr. Möglicherweise möchten Sie jedoch überprüfen, ob sich zwischen Quell- und Zieltabelle nichts geändert hat, während Sie die Kopie erstellt haben. Dies wäre wahrscheinlich ohnehin während der Tabellenerstellung erforderlich, wenn Sie die App nicht daran hindern würden, Änderungen vorzunehmen. Bei einem solchen Vorgang entsteht ein Overhead für die Festplattenleistung.
John Sansom
Persönlich würde ich diesen Ansatz zuerst versuchen, Sie können es mit der Option nolock zum Testen tun, Sie können auch die erforderliche Zeit überprüfen. Wenn es so funktioniert, wie es sollte, würde ich die Datenbank in den Einzelbenutzermodus versetzen, während ich es erneut mache, um sicherzustellen, dass keine Änderungen stattfinden, während der Prozess ausgeführt wird. Die Ausfallzeiten sind bei diesem Ansatz viel kürzer, wenn sie funktionieren.
Baldy
Wenn Sie dies tun, würde ich empfehlen, zuerst die Tabelle zu erstellen (indem Sie die ursprüngliche Tabelle ausschreiben). Verwenden Sie dann "INSERT INTO newTable SELECT" im Vergleich zu "SELECT INTO". Mit "SELECT INTO" können Leistungsprobleme auftreten.
SQL3D
0

Ich würde versuchen, die Daten zuerst in eine Datei zu packen und sie dann wieder in eine neue Tabelle zu packen. SELECT INTO ist für diese Anzahl von Datensätzen nicht geeignet (IMO) ...

m4rty
quelle