Cari objek yang rusak dengan nomor halaman yang rusak di MS SQL Server 2005

Suatu hari salah satu database MS SQL Server beralih ke Suspect, ada pesan kesalahan di log:
Msg 7105, Level 22, Negara Bagian 9, Jalur 14
Database ID 6, halaman (1: 386499), slot 0 untuk node tipe data LOB tidak ada. Ini biasanya disebabkan oleh transaksi yang dapat membaca data yang tidak terikat pada halaman data. Jalankan DBCC CHECKTABLE.

Basis data dipindahkan ke Darurat dan mencoba mengeksekusi DBCC CHECKDB, tetapi eksekusi segera terputus:
Msg 8921, Lantai 16, Negara Bagian 1, Jalur 13
Cek dihentikan Kegagalan terdeteksi saat mengumpulkan fakta. Mungkin tempdb keluar dari ruang atau tabel sistem tidak konsisten. Periksa kesalahan sebelumnya.
Msg 7105, Level 22, Negara Bagian 9, Jalur 13
Database ID 6, halaman (1: 386499), slot 0 untuk node tipe data LOB tidak ada. Ini biasanya disebabkan oleh transaksi yang dapat membaca data yang tidak terikat pada halaman data. Jalankan DBCC CHECKTABLE.

Perintah DBCC CHECKALLOC terganggu dengan kesalahan yang sama. Semuanya menjadi rumit oleh fakta bahwa SQL Server adalah versi 9.0.1399, yaitu RTM, tanpa pembaruan apa pun.

Upaya untuk menggunakan petunjuk TABLOCK dan secara eksplisit meningkatkan tingkat isolasi transaksi tidak mengarah ke apa pun (ada cukup ruang disk dengan tempdb dan DBCC CHECKALLOC dengan DENGAN ESTIMATE saja gagal dengan kesalahan yang sama). Saya benar-benar tidak ingin menggulung SP ke server dengan database yang rusak, dan itu benar-benar tidak dapat dipahami dengan objek spesifik apa masalahnya. Selain itu, tampaknya pesan DBCC CHECKDB tidak ada hubungannya dengan kenyataan, karena ada satu catatan di msdb.dbo.suspect_pages, tetapi nomor halaman berbeda dari yang dicetak oleh DBCC CHECKDB.

Untuk mengikuti instruksi DBCC CHECKDB dan menjalankan DBCC CHECKTABLE, Anda perlu mengetahui tabelnya. Dan setelah pencarian yang panjang, satu instruksi ditemukan .
Catatan
Saya minta maaf bahwa nomor tabel dalam pesan kesalahan dan kode tidak cocok. Saya mengambil kesalahan dari log, dan setelah itu saya mengeksekusi kode di lingkungan pengujian pada yang lain, live base.

Kami menggunakan algoritma di bawah ini untuk menentukan object_id dari kedua halaman - dari DBCC CHECKDB dan suspect_pages. Masalahnya ada di halaman dari suspect_pages

Hal pertama yang harus dilakukan adalah mengeksekusi (dalam konteks database yang rusak) adalah DBCC PAGE (database_id, file_id, page_id, printopt):

DBCC TRACEON (3604); DBCC PAGE(5, 1, 3242342, 0) DBCC TRACEOFF (3604); 

baik:

 DBCC PAGE(5, 1, 3242342, 0) WITH TABLERESULTS. 

Jika Anda beruntung (atau Anda bermain secara live), sebagai hasilnya Anda akan melihat bidang Metadata: ObjectId dan, pada kenyataannya, object_id yang diinginkan:



Namun, jika Anda, seperti kami, tidak beruntung, Anda akan melihat yang berikut:
Metadata: = Tidak tersedia dalam DB offline
Jika metadata tidak tersedia, tidak semuanya hilang, dalam hal ini, kita memerlukan bidang m_objId (AllocUnitId.idObj). Jika m_objId = 255, masalahnya adalah, tutup artikel dan cari sesuatu yang lain (coba skrip semua yang Anda bisa dan hapus data, jalankan DBCC CHECKDB dengan parameter "pemulihan" secara membabi buta, dll.).
Tangkapan layar menunjukkan bahwa saya memiliki m_objId = 9931, mis. bisa terus.

Sekarang Anda perlu melakukan beberapa perhitungan untuk menghitung ID Unit Alokasi (lebih lanjut tentang Unit Alokasi dapat ditemukan di sini ):
ID Unit Alokasi = m_objid * 65536 + (2 ^ 56)
Dalam kasus kami:
ID Unit Alokasi = 9931 * 65536 + (2 ^ 56) = 72057594688765952

Jadi, mengetahui ID Unit Alokasi, Anda dapat melihat apa yang kami miliki di tampilan sistem sys.allocation_units :

 SELECT * FROM sys.allocation_units WHERE allocation_unit_id = 72057594688765952 



Dan di sana, dalam tipe kasus = 1 atau 3 (IN_ROW_DATA, ROW_OVERFLOW_DATA), kolom container_id = sys.partitions.hobt_id ("ID Heap-Atau-B-Tree"), yaitu. Anda dapat menjalankan permintaan:

 SELECT * FROM sys.partitions WHERE hobt_id = 72057594661437440 



Dan di sini sudah ada object_id dan index_id yang benar. Sekarang Anda dapat melihat apa yang kami miliki di sys.objects dan sys.indexes, dan jalankan:

 SELECT OBJECT_NAME(object_id) 

Untungnya, baik dalam situasi nyata dan di sini, indeks non-cluster ternyata dikonfirmasi, setelah restrukturisasi yang semuanya kembali normal (pada kenyataannya, tidak, tapi itu cerita lain).

Referensi :
Cara menggunakan PAGE DBCC
Pemecahan Masalah dan Memperbaiki Korupsi Tingkat Halaman SQL Server
Apa itu Unit Alokasi?
Menemukan nama tabel dari ID halaman
sys.allocation_units

Source: https://habr.com/ru/post/id430824/


All Articles