Suchen Sie nach einem beschädigten Objekt anhand der Nummer der beschädigten Seite in MS SQL Server 2005

    Neulich ging eine der MS SQL Server-Datenbanken zu Suspect. Im Protokoll wurde eine Fehlermeldung angezeigt:
    Meldung 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 Basis wurde an Emergency übergeben und es wurde versucht, DBCC CHECKDB auszuführen, die Ausführung wurde jedoch sofort unterbrochen:
    Meldung 8921, Ebene 16, Status 1, Zeile 13
    Prüfung beendet. Beim Erfassen von Fakten wurde ein Fehler festgestellt. Möglicherweise ist tempdb nicht genügend Speicherplatz oder eine Systemtabelle ist inkonsistent. Überprüfen Sie die vorherigen Fehler.
    Meldung 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.

    Mit demselben Fehler wurde die Ausführung des Befehls DBCC CHECKALLOC unterbrochen. Alles wurde kompliziert durch die Tatsache, 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 nicht zu irgendetwas (auf Festplatten mit tempdb und DBCC CHECKALLOC war genügend Speicherplatz vorhanden, wobei WITH ESTIMATEONLY mit demselben Fehler endete). Es war äußerst unerwünscht, SP auf einem Server mit einer beschädigten Datenbank zu rollen, und es war absolut unverständlich, bei welchem ​​bestimmten Objekt das Problem bestand. Außerdem schien die DBCC CHECKDB-Nachricht wenig mit der Realität zu tun zu haben, da es in msdb.dbo.suspect_pages einen Eintrag gab, die Seitennummer sich jedoch von der von DBCC CHECKDB angezeigten unterschied.

    Um den Anweisungen von DBCC CHECKDB folgen und DBCC CHECKTABLE ausführen zu können, musste die Tabelle bekannt sein. Nach langer Suche wurde eine Anweisung gefunden .
    Hinweis
    Я прошу прощения, что номера таблиц в сообщениях об ошибках и в коде не совпадают. Ошибки я взял из журналов, а код уже после выполняю в тестовом окружении на другой, живой базе.

    Мы использовали алгоритм ниже для определения object_id обеих страниц — из DBCC CHECKDB и suspect_pages. Проблема оказалась в странице из suspect_pages


    Als erstes müssen Sie (im Kontext einer beschädigten Datenbank) DBCC PAGE (Datenbank-ID, Datei-ID, Seiten-ID, Druckoption) ausführen:

    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 als Ergebnis das Feld Metadata: ObjectId und die object_id selbst:



    Wenn Sie jedoch kein Glück haben, sehen Sie Folgendes:
    Metadaten: = In Offline-DB nicht verfügbar
    Wenn die Metadaten nicht verfügbar sind, geht nicht alles verloren. In diesem Fall benötigen wir das Feld m_objId (AllocUnitId.idObj). Wenn m_objId = 255, schließen Sie den Artikel und suchen Sie nach etwas anderem (versuchen Sie, alles Mögliche zu skriften und ziehen Sie die Daten, führen Sie DBCC CHECKDB blind mit "recovery" -Parametern usw. aus).
    Der Screenshot zeigt, dass ich m_objId = 9931 habe, d. H. kann weitergehen.

    Nun müssen Sie einige kleine Berechnungen durchführen, um die Zuordnungseinheiten-ID zu berechnen (weitere Informationen zu Zuordnungseinheiten finden Sie hier ):
    Zuordnungseinheit ID = m_objid * 65536 + (2 ^ 56)
    In unserem Fall
    Zuordnungseinheit ID = 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 wenn type = 1 oder 3 (IN_ROW_DATA, ROW_OVERFLOW_DATA) ist, gilt die Spalte container_id = sys.partitions.hobt_id ("Heap-Or-B-Tree ID"), d. Sie können die Abfrage ausführen:

    SELECT * FROM sys.partitions WHERE hobt_id = 72057594661437440



    Und hier gibt es bereits eine korrekte object_id und eine index_id. Jetzt können Sie sehen, was wir in sys.objects und sys.indexes haben, und führen Sie einfach Folgendes aus:

    SELECT OBJECT_NAME(object_id)

    Glücklicherweise hat sich der Nonclustered-Index in einer realen Situation als richtig herausgestellt, nachdem alles neu erstellt wurde (tatsächlich nicht, aber dies ist eine andere Geschichte).

    Links :
    Verwendung von
    SQL Server-
    Korrekturstufen für Korrekturen.
    Suchen eines Tabellennamens anhand einer Seiten-ID
    sys.allocation_units

    Jetzt auch beliebt: