Это действительно интересный вопрос, который возник на курсе Microsoft Certified Architect, который я сейчас веду: если в базе данных включена защита от «оборванных» страниц (torn-page protection), а затем включаются контрольные суммы страниц (page checksums), теряется ли при этом действующая проверка на torn-page?
Вопрос важный, потому что включение контрольных сумм страниц не приводит к мгновенному появлению checksum на всех уже выделенных страницах (контрольная сумма появится лишь после того, как страница будет прочитана в буферный пул, изменена и затем записана на диск). Если бы существующая torn-page‑защита полностью «отбрасывалась» при включении контрольных сумм, страницы оставались бы без защиты до тех пор, пока на них не появятся checksums. Я не помнил точного ответа, поэтому провёл эксперимент!
Идея была такая: создать базу с включённой "torn page detection", создать таблицу с имитацией оборванной страницы внутри, затем включить контрольные суммы страниц и проверить, будет ли «оборванная» страница по‑прежнему обнаруживаться.
-- Create the test database
USE master;
GOCREATE DATABASE ChecksumTest;
GO
USE ChecksumTest;
GO
-- Explicitly set the database to have torn-page detection
ALTER DATABASE ChecksumTest SET PAGE_VERIFY TORN_PAGE_DETECTION;
GO
-- Create a test table and insert a row.
CREATE TABLE BrokenTable (c1 INT, c2 CHAR (1000));
INSERT INTO BrokenTable VALUES (1, ‘a’);
GO
-- Ensure the page is written to disk and then tossed from the buffer pool
CHECKPOINT;
GO
DBCC DROPCLEANBUFFERS;
GO
Теперь посмотрим на страницу. В заголовке страницы есть два бита, указывающих, защищена ли страница механизмом torn-page или контрольной суммой. Точнее, в поле m_flagBits будет установлен 0x100, если страница закодирована для torn-page‑защиты, и 0x200, если на странице сохранена контрольная сумма и страница не была изменена (то есть checksum всё ещё действительна). Бит 0x100 вы обычно не увидите, потому что torn-page‑кодирование снимается при чтении страницы в буферный пул — КРОМЕ случая, когда страница действительно «оборвана»: тогда кодирование не снимается.
sp_allocationmetadata ‘BrokenTable’;
GO
DBCC TRACEON (3604);
GO
DBCC PAGE (‘ChecksumTest’, 1, 143, 3);
GO
<snip>
m_pageId = (1:143) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x8000
m_objId (AllocUnitId.idObj) = 67 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594042318848
Metadata: PartitionId = 72057594038321152 Metadata: IndexId = 0
Metadata: ObjectId = 2073058421 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 1008 m_slotCnt = 2 m_freeCnt = 6070
m_freeData = 2118 m_reservedCnt = 0 m_lsn = (28:183:2)
m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = 770
<snip>
В данном случае torn-page‑кодирование было снято, и со страницей всё в порядке. После того как я повредил страницу на диске, «поймать» её в DBCC PAGE непросто. Однажды удалось, и я увидел следующее:
m_pageId = (1:143) m_headerVersion = 1 m_type = 1
m_typeFlagBits = 0x4 m_level = 0 m_flagBits = 0x8100
m_objId (AllocUnitId.idObj) = 67 m_indexId (AllocUnitId.idInd) = 256
Metadata: AllocUnitId = 72057594042318848
Metadata: PartitionId = 72057594038321152 Metadata: IndexId = 0
Metadata: ObjectId = 2073058421 m_prevPage = (0:0) m_nextPage = (0:0)
pminlen = 1008 m_slotCnt = 1 m_freeCnt = 7083
m_freeData = 1107 m_reservedCnt = 0 m_lsn = (28:81:20)
m_xactReserved = 0 m_xdesId = (0:0) m_ghostRecCnt = 0
m_tornBits = 41949233
Теперь, если я попробую выбрать данные из таблицы, получаю:
SELECT * FROM BrokenTable;
GO
Msg 824, Level 24, State 2, Line 1SQL Server detected a logical consistency-based I/O error: torn page(expected signature: 0xaaaaaaaa; actual signature: 0xaaaaa82a).It occurred during a read of page (1:143) in database ID 8at offset 0x0000000011e000 in file‘C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\ChecksumTest.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.
Суть вопроса в том, будет ли это по‑прежнему диагностироваться после переключения базы на контрольные суммы страниц. Проверим:
ALTER DATABASE checksumtest SET PAGE_VERIFY CHECKSUM;
GO
SELECT * FROM BrokenTable;
GO
Msg 824, Level 24, State 2, Line 1SQL Server detected a logical consistency-based I/O error: torn page(expected signature: 0xaaaaaaaa; actual signature: 0xaaaaa82a).It occurred during a read of page (1:143) in database ID 8 at offset 0x0000000011e000 in file‘C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\ChecksumTest.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.
Отлично! Ответ — ДА: «оборванная» страница всё равно обнаруживается, потому что бит в заголовке страницы указывает, какой алгоритм защиты применяется к этой странице. Более того, это срабатывает даже если полностью выключить и контрольные суммы страниц, и "torn page detection".

Комментариев нет:
Отправить комментарий