SQL: Kontrolowane uszkodzenie bazy danych

15-Cze-2017

W tym artykule możesz zobaczyć w jaki sposób można uszkodzić bazę danych, więc zgodnie z europejskimi zwyczajami:

Uwaga! Wykonanie poniższych czynności może uszkodzić bazę danych! 🙂

Zacznij od utworzenia bazy danych:

Teraz na wszelki wypadek można wykonać kopię bazy, dzięki temu będzie można szybko rozpoczynać zabawę na nowo

Poznajmy adresację stron:

Polecenie zwraca informację o indeksie clustrowanym . Pierwszy rekord opisuje stronę zwaną IAM (pierwsza strona tabeli), a kolejna to już strona z danymi:

 

 

Jeśli chcemy psuć dane, to dobrym miejscem jest w tym przypadku strona 344 (dziecko strony 245)

Zaczynamy od wyświetlenia zawartości strony 344. Do tego służy komenda DBCC PAGE, ale aby wyświetlała wyniki konieczne jest włączenie trace flagi 3604:

zwróć uwagę na wynik:

Zaznaczone kolorem fragmenty oznaczają:

  • Slot (rekord), a w nim m.innymi offset, czyli przesunięcie od początku strony, gdzie znajduje się ta informacja, memory dump z tekstową prezentacją po prawej stronie
  • Widać też wartości w kolumnach

Można przystępować do psucia. Służy do tego ukryta funkcja DBCC PAGEWRITE. Tak można uzyskać minimalny help do tej funkcji:

Składnia funkcji jest następująca:

dbcc WRITEPAGE ({‚dbname’ | dbid}, fileid, pageid, offset, length, data [, directORbufferpool])

  • dbname – nazwa bazy danych
  • fileid – numer pliku bazy danych
  • pageid – numer strony wyrażony jako liczba dziesiętna
  • length – długość danych, jakie będą zapisane na stronie (od 1 do 8)
  • data – dane do zapisania, hex
  • directORbufferpool – 1 oznacza zapis z pominięciem bufora (checkpoint + zapis na dysk bez przeliczenia checksum) lub 0 – modyfikacja strony w buforze (z przeliczeniem sumy kontrolnej podczas zapisywania strony na dysku)

w naszym przypadku:

Oto jak została wyznaczona liczba 106 – jest to pozycja trzeciej literki ‚A’ w pierwszym rekordzie:

106 = offset (ox60) + pozycja_trzeciej_literki_a_w_rekordzie (10) = 96 + 10

Jeśli wykonasz teraz jakikolwiek zapytanie do tabeli (która cała mieści się na jednej uszkodzonej stronie), to wynikiem będzie:

Msg 824, Level 24, State 2, Line 5
SQL Server detected a logical consistency-based I/O error:
incorrect checksum (expected: 0xdbdd841d; actual: 0x5bdd8411).
It occurred during a read of page (1:344) in database ID 9 at offset 0x000000002b0000 in file
‚C:\Program Files\Microsoft SQL Server\MSSQL13.MSSQLSERVER\MSSQL\DATA\CorruptDB.mdf’.
Additional messages in the SQL Server error log or system event log may provide more detail.
This is a severe error condition that threatens database integrity and must be corrected immediately.
Complete a full database consistency check (DBCC CHECKDB).
This error can be caused by many factors; for more information, see SQL Server Books Online.

Baza jest uszkodzona!

Gdyby w poprzednim kroku zepsuć bazę wykonując polecenie z „0” jako ostatni argument:

to po wszystkim nadal można korzystać z danych:

 

 

 

 

 

Nawet polecenie:

DBCC CHECKDB (‚Corruptdb’) WITH NO_INFOMSGS

nie zwraca żadnych błędów. Dlaczego? Bo zapis został wykonany w obszarze danych znakowych, o opcja „0” w ostatnim argumencie WRITEPAGE powodowała wyliczenie sumy kontrolnej przed zapisem, więc…. błędu nie ma i baza nie będzie uszkodzona, dokonaliśmy po prostu bardzo specyficznego update na rekordzie.

Skorzystałem z:

Paul Randal:

https://www.sqlskills.com/blogs/paul/dbcc-writepage/

DBCC WRITEPAGE: an introduction

https://www.sqlskills.com/blogs/paul/category/dbcc/

Armando Prato: https://www.mssqltips.com/sqlservertip/1578/using-dbcc-page-to-examine-sql-server-table-and-index-data/

Derek Colley https://www.mssqltips.com/sqlservertip/2871/troubleshooting-and-fixing-sql-server-page-level-corruption/

Brent Ozar: https://www.brentozar.com/archive/2014/05/dbcc-checkdb-faq/

Andrew Jackson: http://dbathings.com/dbcc-page-command-analyze-sql-database-objects/

Dodaj komentarz:

Autor: Rafał Kraik