Eines Tages, als eine der MS SQL Server-Datenbanken auf Suspect umgestellt wurde, gab es eine Fehlermeldung im Protokoll:
Nachricht 7105, Ebene 22, Status 9, Zeile 14
Datenbank-ID 6, Seite (1: 386499), Steckplatz 0 für LOB-Datentypknoten ist nicht vorhanden. Dies wird normalerweise durch Transaktionen verursacht, die nicht festgeschriebene Daten auf einer Datenseite lesen können. Führen Sie DBCC CHECKTABLE aus.
Die Datenbank wurde an Emergency übertragen und versucht, DBCC CHECKDB auszuführen, die Ausführung wurde jedoch sofort unterbrochen:
Nachricht 8921, Ebene 16, Status 1, Zeile 13
Prüfung beendet. Beim Sammeln von Fakten wurde ein Fehler festgestellt. Möglicherweise ist Tempdb nicht genügend Speicherplatz oder eine Systemtabelle inkonsistent. Überprüfen Sie frühere Fehler.
Nachricht 7105, Ebene 22, Status 9, Zeile 13
Datenbank-ID 6, Seite (1: 386499), Steckplatz 0 für LOB-Datentypknoten ist nicht vorhanden. Dies wird normalerweise durch Transaktionen verursacht, die nicht festgeschriebene Daten auf einer Datenseite lesen können. Führen Sie DBCC CHECKTABLE aus.
Der Befehl DBCC CHECKALLOC wurde mit einem ähnlichen Fehler unterbrochen. Alles wurde durch die Tatsache kompliziert, dass SQL Server Version 9.0.1399 war, d.h. RTM, ohne Updates.
Versuche, den TABLOCK-Hinweis zu verwenden und die Transaktionsisolation explizit zu erhöhen, führten zu nichts (es gab genügend Speicherplatz mit tempdb und DBCC CHECKALLOC, wobei WITH ESTIMATEONLY mit demselben Fehler fehlgeschlagen war). Ich wollte SP wirklich nicht auf einen Server mit einer beschädigten Datenbank rollen, und es war völlig unverständlich, mit welchem spezifischen Objekt das Problem bestand. Darüber hinaus schien die DBCC CHECKDB-Nachricht wenig mit der Realität zu tun zu haben, da in msdb.dbo.suspect_pages ein Datensatz vorhanden war, die Seitenzahl sich jedoch von der von DBCC CHECKDB gedruckten unterschied.
Um den Anweisungen von DBCC CHECKDB zu folgen und DBCC CHECKTABLE auszuführen, müssen Sie die Tabelle kennen. Und nach langer Suche wurde eine Anweisung
gefunden .
HinweisIch entschuldige mich, dass die Tabellennummern in den Fehlermeldungen und im Code nicht übereinstimmen. Ich habe Fehler aus den Protokollen genommen und danach den Code in einer Testumgebung auf einer anderen Live-Basis ausgeführt.
Wir haben den folgenden Algorithmus verwendet, um die Objekt-ID beider Seiten zu bestimmen - aus DBCC CHECKDB und verdächtigen Seiten. Das Problem war auf der Seite von verdächtigen_Seiten
Das erste, was zu tun ist, ist die Ausführung (im Kontext einer beschädigten Datenbank) der
DBCC-SEITE (Datenbank-ID, Datei-ID, Seiten-ID, Druckoption):
DBCC TRACEON (3604); DBCC PAGE(5, 1, 3242342, 0) DBCC TRACEOFF (3604);
entweder:
DBCC PAGE(5, 1, 3242342, 0) WITH TABLERESULTS.
Wenn Sie Glück haben (oder auf einer Live-Basis spielen), sehen Sie das Feld Metadaten: Objekt-ID und tatsächlich die gewünschte Objekt-ID:

Wenn Sie jedoch wie wir Pech haben, werden Sie Folgendes sehen:
Metadaten: = In der Offline-Datenbank nicht verfügbar
Wenn keine Metadaten verfügbar sind, geht nicht alles verloren. In diesem Fall benötigen wir das Feld m_objId (AllocUnitId.idObj). Wenn m_objId = 255, besteht das Problem darin, den Artikel zu schließen und nach etwas anderem zu suchen (versuchen Sie, alles zu skripten, was Sie können, und entfernen Sie die Daten, führen Sie DBCC CHECKDB mit den "Wiederherstellungs" -Parametern blind aus usw.).
Der Screenshot zeigt, dass ich m_objId = 9931 habe, d.h. kann weitergehen.
Jetzt müssen Sie einige Berechnungen durchführen, um die ID der Zuordnungseinheit zu berechnen (weitere Informationen zu Zuordnungseinheiten finden Sie
hier ):
ID der Zuordnungseinheit = m_objid * 65536 + (2 ^ 56)
In unserem Fall:
ID der Zuordnungseinheit = 9931 * 65536 + (2 ^ 56) = 72057594688765952
Wenn Sie also die Allocation Unit ID kennen, können Sie in der Systemansicht
sys.allocation_units sehen, was wir haben:
SELECT * FROM sys.allocation_units WHERE allocation_unit_id = 72057594688765952

Und dort, falls Typ = 1 oder 3 (IN_ROW_DATA, ROW_OVERFLOW_DATA), die Spalte container_id = sys.partitions.hobt_id ("Heap-Or-B-Tree ID"), d.h. Sie können die Anforderung ausführen:
SELECT * FROM sys.partitions WHERE hobt_id = 72057594661437440

Und hier gibt es bereits die richtige object_id und index_id. Jetzt können Sie sehen, was wir in sys.objects und sys.indexes haben, und einfach ausführen:
SELECT OBJECT_NAME(object_id)
Glücklicherweise stellte sich sowohl in der realen Situation als auch hier heraus, dass der Nicht-Cluster-Index bestätigt wurde, nach dessen Umstrukturierung sich alles wieder normalisierte (tatsächlich nein, aber das ist eine andere Geschichte).
Referenzen :
Verwendung von DBCC PAGEFehlerbehebung und Behebung von Beschädigungen auf SQL Server-SeitenebeneWas sind Allokationseinheiten?Suchen eines Tabellennamens aus einer Seiten-IDsys.allocation_units