7.10.25

Отключается ли "torn page detection" при включении "page checksums"?

Автор: Paul Randal, Inside The Storage Engine: Does turning on page checksums discard any torn-page protection?

Это действительно интересный вопрос, который возник на курсе 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 1
SQL 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.

Суть вопроса в том, будет ли это по‑прежнему диагностироваться после переключения базы на контрольные суммы страниц. Проверим:

ALTER DATABASE checksumtest SET PAGE_VERIFY CHECKSUM;
GO

SELECT * FROM BrokenTable;
GO

Msg 824, Level 24, State 2, Line 1
SQL 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".




Комментариев нет:

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