TL; DR: Saya mengalami korupsi yang tidak dapat diperbaiki dalam tampilan yang diindeks. Berikut detailnya:
Lari
DBCC CHECKDB([DbName]) WITH EXTENDED_LOGICAL_CHECKS, DATA_PURITY, NO_INFOMSGS, ALL_ERRORMSGS
di salah satu database saya menghasilkan kesalahan berikut:
Msg 8907, Level 16, State 1, Line 1 Indeks spasial, indeks XML atau tampilan terindeks 'ViewName' (objek ID 784109934) berisi baris yang tidak diproduksi oleh definisi tampilan. Ini tidak selalu mewakili masalah integritas dengan data dalam database ini. (...)
CHECKDB menemukan 0 kesalahan alokasi dan 1 kesalahan konsistensi pada tabel 'ViewName'.
repair_rebuild adalah level perbaikan minimum (...).
Saya mengerti bahwa pesan ini menunjukkan bahwa data material dari tampilan yang diindeks 'ViewName' tidak identik dengan apa yang dihasilkan oleh kueri yang mendasarinya. Namun, memverifikasi data secara manual tidak menimbulkan perbedaan apa pun:
SELECT * FROM ViewName WITH (NOEXPAND)
EXCEPT
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
SELECT ...
from T1 WITH (FORCESCAN)
join T2 on ...
EXCEPT
SELECT * FROM ViewName WITH (NOEXPAND)
NOEXPAND
digunakan untuk memaksa penggunaan indeks (hanya) pada ViewName
. FORCESCAN
digunakan untuk mencegah pencocokan tampilan indeks. Rencana pelaksanaan mengkonfirmasi kedua langkah tersebut berfungsi.
Tidak ada baris yang dikembalikan di sini, artinya kedua tabel identik. (Hanya ada kolom integer dan guid, collations tidak ikut bermain).
Kesalahan tidak dapat diperbaiki dengan membuat ulang indeks pada tampilan atau dengan menjalankan DBCC CHECKDB REPAIR_ALLOW_DATA_LOSS
. Mengulangi perbaikan juga tidak membantu. Mengapa DBCC CHECKDB
melaporkan kesalahan ini? Bagaimana cara menghilangkannya?
(Bahkan jika pembangunan kembali memperbaikinya, pertanyaan saya akan tetap berlaku - mengapa kesalahan dilaporkan meskipun kueri pemeriksaan data saya berhasil?)
Pembaruan: Bug telah diperbaiki dalam beberapa rilis. Aku tidak bisa lagi mereproduksi dalam SQL Server 2014 SP2 CU 5. 2014 SP2 KB mengandung memperbaiki tanpa artikel KB: Creating non-clustered index causes DBCC CheckDB With Extended_Logical_Checks to raise corruption error
. Dua bug koneksi tentang ini telah ditutup:
- https://connect.microsoft.com/SQLServer/feedback/details/847233/creating-non-clustered-index-causes-dbcc-checkdb-with-extended-logical-checks-to-raise-corruption-error
- https://connect.microsoft.com/SQLServer/feedback/details/795478/unfixable-dbcc-checkdb-error-that-is-also-a-false-positive-and-otherwise-strange
If the indexed view does not contain an aggregate over values of type float or real and you receive errors 8907 or 8708, drop the index on the view and re-create it. Do not use ALTER INDEX REBUILD to try to remove the differences between the stored and the computed view, because ALTER INDEX REBUILD does not recalculate the view before rebuilding the index. Then run DBCC CHECKTABLE on the View to verify no differences remain.
[1]
notasi tidak bekerja dalam komentar mark-down.Jawaban:
Prosesor permintaan dapat menghasilkan rencana pelaksanaan yang tidak valid untuk permintaan (benar) yang dihasilkan oleh DBCC untuk memeriksa bahwa indeks tampilan menghasilkan baris yang sama dengan permintaan tampilan yang mendasarinya.
Rencana yang dihasilkan oleh prosesor query salah menangani
NULLs
untukImageObjectID
kolom. Itu salah alasan permintaan tampilan menolakNULLs
untuk kolom ini, padahal tidak. Berpikir yangNULLs
dikecualikan, itu dapat mencocokkan indeks nonclustered disaring padaUsers
tabel yang difilterImageObjectID IS NOT NULL
.Dengan menghasilkan rencana yang menggunakan indeks yang difilter ini, memastikan bahwa baris dengan
NULL
inImageObjectID
tidak ditemui. Baris-baris ini dikembalikan (dengan benar) dari indeks tampilan, jadi sepertinya ada korupsi saat tidak ada.Definisi tampilan adalah:
The
ON
klausul kesetaraan perbandingan antaraAdminUserID
danID
menolakNULLs
di kolom tersebut, tetapi bukan dariImageObjectID
kolom.Bagian dari permintaan yang dihasilkan DBCC adalah:
Ini adalah kode umum yang membandingkan nilai-nilai secara
NULL
sadar. Ini memang verbose, tetapi logikanya baik-baik saja.Bug dalam penalaran prosesor kueri berarti bahwa rencana kueri yang salah menggunakan indeks yang difilter dapat dihasilkan, seperti dalam contoh fragmen paket di bawah ini:
Permintaan DBCC mengambil jalur kode yang berbeda melalui prosesor permintaan dari permintaan pengguna. Jalur kode ini berisi bug. Ketika sebuah rencana menggunakan indeks yang difilter dihasilkan, itu tidak dapat digunakan dengan
USE PLAN
petunjuk untuk memaksa bentuk rencana itu dengan teks kueri yang sama yang dikirimkan dari koneksi database pengguna.Jalur kode pengoptimal utama (untuk kueri pengguna) tidak mengandung bug ini, jadi khusus untuk kueri internal seperti yang dihasilkan oleh DBCC.
sumber
Investigasi lebih lanjut menunjukkan bahwa ini adalah bug dalam DBCC CHECKDB. Bug Microsoft Connect telah dibuka: Kesalahan DBCC CHECKDB yang tidak dapat diperbaiki (itu juga merupakan false positive dan sebaliknya aneh) . Untungnya, saya bisa menghasilkan repro sehingga bug dapat ditemukan dan diperbaiki.
Bug dapat disembunyikan dengan bermain dengan skema database. Menghapus indeks terfilter yang tidak terkait, atau menghapus filter, menyembunyikan bug. Untuk detailnya, silakan lihat item terhubung.
Item terhubung juga berisi permintaan internal yang digunakan DBCC CHECKDB untuk memvalidasi konten tampilan. Itu tidak mengembalikan hasil, menunjukkan bahwa ini adalah bug.
Bug telah diperbaiki dalam beberapa rilis. Saya tidak bisa lagi mereproduksi di SQL Server 2014 SP2 CU 5.
sumber