Header RSS-подписка на обновления сайта eMail-подписка на обновления сайта

Как SQL Server находит оборванные страницы и зачем он этим занимается. Часть 2/2.

  • Другие части статьи:
  • 1
  • 2
  • вперед »

Исследование и анализ различных режимов работы.


366bef3a

Вот теперь, зная как режимы переключаются, мы имеем полное право перейти к «подтверждению теории практикой», а проще говоря — к исследованию всех трех режимов и их влиянию на устойчивость сохраняемых данных. План наших работ примерно такой:

  • создать тестовую базу;
  • установить для нее каждый из трех возможных режимов последовательно;
  • внести на одну из страниц тестовой базы какую-то информацию;
  • вызвать заголовок этой страницы и проанализировать значения полей m_flagBits/m_tornBits;
  • отсоединить базу;
  • с помощью HEX-редактора внести прямые изменения в страницу, имитируя тем самым «сбой контроллера» или «осыпание HDD»;
  • подключить базу обратно;
  • проанализировать сообщения об ошибках (если таковые будут возвращены сервером).

Собственно — давайте сразу же к реализации нашего плана:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
USE master
go
CREATE DATABASE TstPageProtect
ON PRIMARY (
    NAME = 'TstPP_Data',
    FILENAME = 'c:\sqlCMD.ru\TstPP_Data.mdf',
    SIZE = 5 MB,
    MAXSIZE = 5 MB )
LOG ON (
    NAME = 'TstPP_Log',
    FILENAME = 'c:\sqlCMD.ru\TstPP_Log.ldf',
    SIZE = 1 MB,
    MAXSIZE = 1 MB )
GO
ALTER DATABASE TstPageProtect SET RECOVERY SIMPLE
GO
ALTER DATABASE TstPageProtect SET PAGE_VERIFY CHECKSUM
GO
USE TstPageProtect
GO
CREATE TABLE T1 (C1 INT IDENTITY, C2 INT NOT NULL, C3 VARCHAR(10) NOT NULL)
GO
INSERT INTO T1 VALUES (10, 'AaaaXxxx')
INSERT INTO T1 VALUES (20, 'BbbbYyyy')
INSERT INTO T1 VALUES (30, 'CcccZzzz')
DBCC IND(TstPageProtect, T1, -1)
DBCC TRACEON(3604)
DBCC PAGE(TstPageProtect, 1, 79, 0)
Если вам не совсем понятно почему для извлечения заголовка страницы мы используем пару команд DBCC IND/DBCC PAGE или вам интересен смысл параметров этих команд, обращайтесь к части второй статьи «Как перестать называть журнал транзакций SQL Server лог-файлом и прекратить борьбу за его размер». В указанной статье обе команды разобраны до известной степени подробности. Там же вы можете найти пояснения на тему почему в вашем конкретном тестовом окружении возможно придется поменять значения параметров второй из команд. А так же указания как и откуда извлечь эти «правильные» значения. Помимо этого, не забудьте создать на диске C: папку sqlCMD.ru или дополнительно модифицировать показанный скрипт.

Как видите, мы начинаем исследования режимов в обратном порядке. Сначала исследуем режим наиболее продвинутый, тот что сохраняет контрольные суммы страниц. Как мы знаем из теории в этом режиме каждая из страниц (и наша исследуемая страница 1:79 не исключение) должна иметь в поле m_tornBits просчитанную контрольную сумму. Ну а в поле m_flagBits один из битов должен обозначить факт присутствия этой самой суммы, правда мы не знаем какой именно из битов. Что бы внести ясность в этот вопрос автор вам сообщит, что если значение указанного поля соединить побитовым AND c числом 0x200 (т.е. выполнить операцию m_flagBits & 0x200) и результатом будет не ноль — искомый бит установлен. Хорошо, запускаем тестовый скрипт и...

m_flagBits = 0x8000/m_tornBits = 0

Нда. Покамест полные «несовпадатушки» с теорией: и искомый бит не установлен, и контрольной суммы нет. Начинаем думать — где мы неправильно понимаем. Ага, есть идея! Ведь как известно checksum просчитывается непосредственно перед сбросом страницы на диск, а до того момента эта сумма просто никому не нужна. Если страница даже не пробовала зафиксировать себя на HDD — чего ж проверять целостность такой несуществующей фиксации, логично? Значит надо стимулировать сброс страницы на диск. Читатели статьи упомянутой чуть выше, да и не только они, прекрасно знают как это делается — да, достаточно выполнить «ручную» контрольную точку, она же CHECKPOINT. Хорошо, давайте для чистоты эксперимента, сбросим нашу базу

1
2
3
USE master
GO
DROP DATABASE TstPageProtect

а между строками 25-26 скрипта исходного вставим требуемую T-SQL команду:

23
24
25
26
27
INSERT INTO T1 VALUES (10, 'AaaaXxxx')
INSERT INTO T1 VALUES (20, 'BbbbYyyy')
INSERT INTO T1 VALUES (30, 'CcccZzzz')
CHECKPOINT
DBCC IND(TstPageProtect, T1, -1)

Пробуем по новой, уже с CHECKPOINT-ом:

m_flagBits = 0x8200/m_tornBits = -654363765

О! Это ж совсем другие «песни»! Вот вам бит, а вот вам сумма. Если мы теперь попробуем вносить самые незначительные изменения в ячейки нашей таблицы и контролировать изменения суммы

1
2
3
4
5
6
UPDATE T1 SET C2=11 WHERE C2=10
CHECKPOINT
DBCC PAGE(TstPageProtect, 1, 79, 0)
UPDATE T1 SET C2=12 WHERE C2=11
CHECKPOINT
DBCC PAGE(TstPageProtect, 1, 79, 0)

то мы быстро убедимся — изменение даже одного бита приводит к совершенно иной контрольной сумме. То есть работает именно алгоритм, а не простое «байт плюс байт». OK, испытаем этот алгоритм на устойчивость. Отключаем базу:

1
2
3
4
--detach
USE master
GO
sp_detach_db 'TstPageProtect'

Открываем в любом hex-редакторе файл c:\sqlCMD.ru\TstPP_Data.mdf и правим его допустим вот как:

EditMDF_file

То есть в колонке C3 первой строки меняем местами два байта не меняя их значений. Это довольно неприятный вариант «сбоя» и неплохая проверка нашему алгоритму. Подключаем базу с ошибкой обратно:

1
2
3
4
--attach
USE master
GO
sp_attach_db 'TstPageProtect', 'c:\sqlCMD.ru\TstPP_Data.mdf'

Пока что у нас

Command(s) completed successfully.

Многие ожидают от режима CHECKSUM такого уровня контроля, что проблемные страницы детектируются мгновенно, как только они появились. Отнюдь! Ведь что бы контрольная сумма «сработала» страница с нею должна быть считана в память, а сумма вычислена повторно. Если мы подключаем базу на 100ГБ, состоящую из нескольких миллионов(!) страниц, то, наверно, будет неразумно забросив все прочие дела (и в ущерб прочим базам, размещенным на том же сервере), «зарубиться» в проверку этих самых нескольких миллионов. Этого и не происходит. И лишь когда эта страница не может быть не считана в память, например, в нашем случае по команде

1
2
3
USE TstPageProtect
GO
SELECT * FROM dbo.T1 WHERE C2<20

CHECKSUM сработает и мы получаем законное:

Msg 824, Level 24, State 2, Line 1
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0xd8b4b38b; actual: 0x58b4af17).
It occurred during a read of page (1:79) in database ID 13 at offset 0x0000000009e000 in file 'c:\sqlCMD.ru\TstPP_Data.mdf'.
Additional messages in the SQL Server error log or...

Если же подсоединяемая база подозрительна вам просто «потому что вот» и вы настаиваете на принудительной проверке «и сразу», и готовы выделить на нее силы/время/ресурсы, то команда DBCC CHECKDB обеспечит вас искомым. Если дело дошло до таких крайностей я рекомендую запускать полную версию указанной команды (т.е. без всяких опций) и проводить стандартный набор проверок. Однако если вы хотите несколько сократить время работы этой «тяжелой» команды, но при этом все же узнать корректность контрольных сумм на каждой из страниц данных — опция PHYSICAL_ONLY той же команды DBCC CHECKDB обеспечит вам и такой подход. Указанная опция проводит лишь критические тесты на предмет физической целостности данных. Просчет и сличение контрольных сумм — один из таких тестов.

Не лишним будет замечание, что если клиент пропустил ошибку 824 (хотя для игнорирования ошибок с уровнем серьезности 24 нужен особый талант программирования), а вы, как администратор системы, не удосужились заглянуть в журнал ошибок SQL Server (а если бы, кстати, вы туда все же заглянули то непременно обнаружили бы там)

Error824_in_log

то SQL Server все же даст вам третий шанс заметить эту самую очень серьезную ошибку. Для этого вам нужно периодически «сканировать» системную таблицу suspect_pages принадлежащую базе msdb. Если сделать это прямо сейчас

1
SELECT * FROM msdb..suspect_pages

то результат будет:

database_id file_id page_id event_type  error_count last_update_date
13          1       79      2           1           2012-04-22 20:27:49.813

Одним словом, информация об ошибке дублируется трижды (уух!), и не надо потом говорить «а я не заметил». Ошибки такого калибра SQL-администратор замечать обязан, иначе он получает не зарплату, а «зряплату».

Так вот, как мы только что убедились алгоритм вычисления контрольных сумм «засекает» даже перестановку байт, что уж там говорить об изменении их значений. Очень, очень неплохо! Сможет ли дать «симметричный ответ» второй режим контроля, TORN_PAGE_DETECTION? Давайте смотреть...

Сбросим нашу тестовую базу и пока она удаляется вспомним — что должно быть в заголовке страниц подвергшихся контролю по технологии «обнаружения обрыва». Тут уже, как говорит нам теория, в поле m_tornBits будет не CHECKSUM, а «биты 15-ти секторов»+«биты контроля, 01/10». Ну а в поле m_flagBits будет отдельный бит, сообщающий, что страница в данный момент кодирована для обнаружения обрыва и не подлежит нормальной работе с нею, т.е. например извлекать с нее данные нельзя. Только сам бит этот нам неизвестен. Но тут снова на выручку приходит ваш автор который и сообщает, что если операция m_flagBits & 0x100 возвращает ноль — страница декодирована и может использоваться в нормальном режиме. А вот если та же операция вернет не ноль — страница кодирована, и что бы начать ее эксплуатацию следует предварительно вернуть «биты на место». Вспомнив всю указанную информацию, и учтя, что кодирование страницы так же происходит лишь при ее записи на диск, а поэтому без CHECKPOINT-а нам не обойтись, запускаем очередной тест:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
USE master
go
CREATE DATABASE TstPageProtect
ON PRIMARY (
    NAME = 'TstPP_Data',
    FILENAME = 'c:\sqlCMD.ru\TstPP_Data.mdf',
    SIZE = 5 MB,
    MAXSIZE = 5 MB )
LOG ON (
    NAME = 'TstPP_Log',
    FILENAME = 'c:\sqlCMD.ru\TstPP_Log.ldf',
    SIZE = 1 MB,
    MAXSIZE = 1 MB )
GO
ALTER DATABASE TstPageProtect SET RECOVERY SIMPLE
GO
ALTER DATABASE TstPageProtect SET PAGE_VERIFY TORN_PAGE_DETECTION
GO
USE TstPageProtect
GO
CREATE TABLE T1 (C1 INT IDENTITY, C2 INT NOT NULL, C3 VARCHAR(10) NOT NULL)
GO
INSERT INTO T1 VALUES (10, 'AaaaXxxx')
INSERT INTO T1 VALUES (20, 'BbbbYyyy')
INSERT INTO T1 VALUES (30, 'CcccZzzz')
CHECKPOINT
DBCC IND(TstPageProtect, T1, -1)
DBCC TRACEON(3604)
DBCC PAGE(TstPageProtect, 1, 79, 0)

Ключевые для нашего обсуждения поля заголовка 79-й страницы на этот раз сообщают нам:

m_flagBits = 0x8000/m_tornBits = 357913941

Ну — с полем вторым все более-менее ясно: первые 30 бит это биты из 15-ти секторов, и последние два (они, кстати, в настоящий момент равны 01) — «биты контроля». Несколько настораживает поле первое — почему нет бита кодирования для обнаружения обрыва? Разве мы не заставили эту процедуру только что исполниться? Заставили! И на диске значение поля m_flagBits прямо сейчас 0x8100. Но мы-то смотрим на страницу (и ее заголовок) в памяти, а не на HDD! А когда страница кодированная по обсуждаемой технологии считывается в память она декодируется, и если сбойных секторов не обнаружено то бит поля m_flagBits очищается и — пожалуйста, пользуйтесь вашей страницей на здоровье. Одним словом, увидеть тот самый бит поля m_flagBits во «взведенном» состоянии можно только при одном условии: при чтении страницы в память обнаружен хотя бы один сбойный сектор. Лишь в этом случае бит кодирования не очищается, а само обратное декодирование не выполняется (да и то, как мы знаем из вводной части, в серверах версий 2005-й и более поздних). Пока у нас «все OK» мы не имеем «счастья» видеть поле m_flagBits с установленным флагом, по крайней мере пока мы анализируем это поле беря его значения из RAM, а не с HDD.

Если же мы теперь попробуем вновь незначительно менять содержимое страницы

1
2
3
4
5
6
UPDATE T1 SET C2=11 WHERE C2=10
CHECKPOINT
DBCC PAGE(TstPageProtect, 1, 79, 0)
UPDATE T1 SET C2=12 WHERE C2=11
CHECKPOINT
DBCC PAGE(TstPageProtect, 1, 79, 0)

то увидим, что все изменение поля m_tornBits сводятся к переключению двух последних бит: 357913941 → 357913942 → 357913941 → и т.д. Это и понятно — финальные биты секторов не меняются, а меняется лишь «шаблон проверки», с 01 на 10 и обратно. Все это вызывает смутную тревогу и нехорошие ожидания, тот же CHECKSUM реагировал на изменения куда как «динамичнее»...

Но — ладно, вновь переходим к прямому редактированию MDF-файла с целью проверки нашего второго подопечного — как он справится с нашими «фокусами»? Отключаем тестовую базу и вносим, например, вот какие изменения:

EditMDF_file2

То есть ошибки куда как более грубы, чем в первом эксперименте: 6 из 8 байт колонки C3 первой строки поменяли свои значения. Нет сомнений, CHECKSUM «просек» бы происходящее просто «влет», а что скажет TORN_PAGE_DETECTION? Подключаем базу, контрольный запрос

1
2
3
USE TstPageProtect
GO
SELECT * FROM dbo.T1 WHERE C2<20

и...

C1  C2  C3
1   12  AgggXqqq

:( Хотя — чего вы ждали? Сбой при записи страницы был? Не был. Сектора все успешно зафиксированы? Все. Вопросы есть? Ну, как бы... Вроде придраться не к чему, все обещанное выполняется, однако после работы с CHECKSUM остается стойкое ощущение дискомфорта. И да, как вы правильно догадались, ни DBCC CHECKDB, ни иные ухищрения не могут в данном случае выявить совершенно ничего — у страницы нет информации о ее верном внутреннем состоянии и все тут! Ну так — «программа-минимум», что с нее взять...

Итак, TORN_PAGE_DETECTION вернет клиенту ошибку 824 (а равно поместит ее в журнал ошибок SQL Server, а равно в системную таблицу suspect_pages) только если сбой произошел на уровне сектора. Содержимое же сектора (каждого по отдельности, а так же всех составляющих страницу вместе) эту технологию не интересует совершенно.

Наконец обзор работы третьего, и завершающего режима NONE будет чрезвычайно лаконичным. Поле m_flagBits заголовка страницы не используется им вообще никак, поле m_tornBits, по сути, тоже, поскольку туда «забивается» константный ноль, который не изменяется ни при каких обстоятельствах. Единственное что хорошо с этим нулем — он как бы сообщает нам об отключении обоих вариантов контроля целостности данных. Теперь с помощью HEX-редактора вы можете «корежить» страницы как угодно, а к тому же при фиксации страницы на HDD писать любое число секторов из 16-ти ее составляющих. Ошибку 824 вы тут получите разве что «отрезав» половину MDF файла ну или предприняв иные сходные по масштабу деструктивные действия. Как было сказано в теоретической части «генеральный» принцип для этого режима очень прост: «проблемы администратора — не есть проблемы сервера».

Сочетание режимов контроля целостности на уровне базы и на уровне отдельной страницы.

Как ни странно, но многими администраторами не осознается тот очевидный факт, что три разобранных нами только что режима контроля целостности существуют сразу на двух уровнях: уровне всей базы и уровне отдельной страницы. Скажем база данных долгое время работала в режиме NONE, а затем администратор перевел ее в режим CHECKSUM. По причинам обсужденным нами выше (а именно — экономия ресурсов) движок сервера вовсе не бросится подсчитывать контрольные суммы для всего миллиона страниц. По большому счету сразу после переключения режима вообще ничего не произойдет. Как было у всех страниц в заголовке поле m_tornBits равным нулю, так все и останется. Ощутимые изменения начнутся лишь тогда, когда страницы данных будут снова сбрасываться на диск (а произойдет это, заметим, не ранее чем когда они станут «грязными»). Вот тут уже новый режим проявит себя вполне, поле m_tornBits получит требуемое значение контрольной суммы. Но не до этого момента! Многие SQL-специалисты спрашивают, можно ли в описанном сценарии провести «форсированный пересчет» контрольных сумм (или же не менее форсированный расчет «битов контроля», если переключение было из режима NONE в режим TORN_PAGE_DETECTION)? При ответе на этот вопрос не вызывают сомнения два факта. Первый: для достижения поставленной цели вам нужно считать все страницы данных в RAM, обязательно изменить их (иначе они не станут «грязными» и не будут нуждаться в сохранении на диск), и зафиксировать эти изменения на диске. И факт второй: SQL Server не предлагает отдельной команды для реализации факта первого. Увы! Можно пытаться достичь цели косвенно, например запустив перестроение всех кластерных и всех не кластерных индексов. Тогда с большой степенью вероятности значительная часть страниц (но определенно не 100%!) будет подвергнута перестроению и, как следствие, реально переключится в новый режим. Однако страницы содержащие, к примеру, код хранимых процедур, код функций, код CLR-сборок и многие другие затронуты не будут, а поэтому останутся в режиме старом. Автору известна единственная (и довольно трудоемкая операция) по гарантированному переключению совершенно всех страниц данных в новый режим:

  • создается новая, совершенно чистая база данных изначально находящаяся в требуемом режиме;
  • база существующая скриптуется, т.е. создаются скрипты воспроизводящие как структуру этой базы, так и наполнение этой структуры информацией;
  • скрипты из пункта 2 запускаются на базе из пункта 1;
  • база из пункта 1 обеспечивает нам желаемую цель.

Как видите, выставить правильный режим с самого начала — много, много проще чем форсировать его переключение позже. Впрочем, если вы не возражаете против «отложенного переключения» — нет проблем, база со временем перейдет в новый режим «естественным путем» и никаких сверхусилий от вас не потребуется.

Итак, бесспорным является тот факт, что база данных всегда находится четко в одном из трех возможных режимов. И тоже самое можно сказать о каждой отдельной странице данных той же базы. Но вот в совокупности те же страницы запросто могут разделять все три режима в одно и то же время. Как сервер со всем этим справляется? А вот как.

Когда страницу нужно записать, то безусловно действует режим установленный на уровне базы. Поля m_flagBits/m_tornBits заголовка страницы получают значения предписываемые этим самым режимом и страница фиксируется на HDD. Тут все несложно, как видите. Но вот когда дело доходит до чтения, то все становится гораздо интереснее:

  • если страница была сохранена в режиме NONE, то неважно что там предписывает база — все проверки пропускаются. Собственно — вы могли бы предложить иной вариант поведения?
  • а вот если у самой базы включен режим NONE, то варианты можно было бы предложить разные, однако и в этом случае поведение будет как и в пункте предыдущем. Т.е. все проверки пропускаются и не важно что там говорит заголовок страницы;
  • если и база, и страница имеют режимы контроля целостности отличные от NONE, то реальный метод проверки осуществляемый при чтении всегда определяется режимом страницы. А не базы. Снова, если немного подумать, то легко понять, что для данного пункта это единственно возможное поведение системы.

Так что у нас подчас страницы «рулят» базой. А не наоборот.

Режимы контроля целостности страниц и резервных копий.

Многие знают, что команды BACKUP/RESTORE имеют в своем синтаксисе опцию одноименную одному из трех режимов, а именно опцию CHECKSUM (которая является именно опцией, т.к. по умолчанию работает вариант ей противоположный — NO_CHECKSUM). Так же многие знают что именно делает эта опция — записывает (если это BACKUP) или считывает (если это RESTORE) контрольную сумму в/из заголовок бэкапа. А вот что многие не знают, как это то, что обсуждаемая контрольная сумма и контрольная сумма в полях m_tornBits страниц — вообще никак не связаны, то есть абсолютно. Автору доводилось даже слышать мнение, что «CHECKSUM бэкапа есть сумма CHECKSUM-ов отдельных страниц в него входящих», что, конечно же, полная нелепость. На самом деле, у двух контрольных сумм лишь одна «точка соприкосновения»— их обе рассчитывает один и тот же алгоритм. Однако для CHECKSUM-а страницы входным набором байт являются все байты этой самой страницы, для CHECKSUM-а же бэкапа — соответственно, все байты этого бэкапа. Поэтому, как легко догадаться, вы можете комбинировать обе технологии в любом сочетании. Например у вас может быть база работающая в режиме контроля NONE, а бэкап ее будет с контрольной суммой. А может быть и база в режиме CHECKSUM, чей бэкап никаких контрольных сумм содержать не будет. Одним словом — полная независимость.

Еще один тонкий момент заслуживает упоминания: BACKUP/RESTORE никак и никогда не влияют на режим контроля ни всей базы, ни отдельных страниц в нее входящих. Иными словами, сразу после RESTORE база данных будет гарантированно иметь тот же самый режим контроля что был у нее на момент работы команды BACKUP. И каждая отдельная страница будет иметь в своем заголовке то что было там на тот же момент времени. Поэтому очередное заблуждение насчет того, что «при восстановлении базы ее страницы будут иметь тот же режим, что и вся база» (т.е. случится тот самый «форсированный пересчет», что мы обсуждали чуть выше) является заблуждением и ничем иным. Страницы будут в том же режиме, что были на момент создания бэкапа, точка.

Режимы контроля — какой выбрать?

В принципе, в отличии от массы других опций предлагаемых SQL сервером где выбор среди альтернатив долог и мучителен, в нашем случае выбор кристально ясен — CHECKSUM для 99.99% реальных систем работающих на платформе SQL Server. Напомню, что начиная с версии 2005 указанный вариант является режимом контроля по умолчанию для всех новых баз и это очень правильно, тут никаких сомнений быть не может. Для порядка рассмотрим все три варианта:

  • NONE — что про него сказать? меньше всех «грузит» систему, да. Однако по причинам излагаемым далее может заинтересовать вас только если вы готовитесь к чемпионату мира по скоростному исполнению T-SQL запросов. Для прочих же решений полное отключение контроля целостности данных с большой степенью вероятности станет началом конца этих самых решений;
  • TORN_PAGE_DETECTION — в качестве аргумента выбора этой альтернативы приводят мысль что «запись целого числа (30 бит из секторов + 2 бита контроля), очевидно, проще чем просчет некоего (пусть и не очень сложного) алгоритма на 8КБ информации». Собственно говоря, никаких иных аргументов в поддержку TORN_PAGE_DETECTION привести и не получится, во всем остальном опция следующая легко обходит его на несколько «корпусов». А по поводу «проще» — обсудим там же, в опции следующей.
  • CHECKSUM — наш безусловный чемпион. Да, нагрузка максимальна, но! Многие не учитывают того простого факта, что эта максимальная нагрузка ложится исключительно на CPU. Смотрите, при записи контрольная сумма вычисляется процессором в памяти, а на диск выводятся ровно те же 8КБ что были бы записаны и в режиме NONE. И со считыванием с HDD аналогично: читаются абсолютно те же 8КБ, а повторный расчет суммы и ее сличение с суммой исходной происходят снова в памяти. Таким образом, самая проблемная часть подавляющего большинства современных SQL-систем (автор говорит, конечно же, о дисковой подсистеме) остается совершенно «нетронутой». А что же до процессора, то он весьма редко становится «узким местом», обычно все упирается в возможности «прокачки» HDD. Таким образом обмен «небольшая добавочная нагрузка на CPU» vs. «значительно более тщательный контроль целостности данных» становится не просто выгодным, а мега-выгодным. Да и тестовые замеры (выполненные как автором данного блога лично, так и его зарубежными коллегами) неопровержимо свидетельствуют: с точки зрения практики, общая производительность среднего решения на типичном оборудовании класса «обычный сервер» не отличима находится ли база в режиме NONE, TORN_PAGE_DETECTION или CHECKSUM. То есть невозможно уверенно утверждать является ли прирост производительности в +0.5% «выгодой» режима NONE или же погрешностью конкретного замера. А у автора пару раз база в CHECKSUM показала в тестах лучшее время, чем она же в режиме NONE. :) Доли процента — но лучше. Чего, конечно, быть не может, но что лишний раз доказывает: все разговоры о «быстрее» в обсуждаемом контексте крутятся, так или иначе, вокруг погрешности измерений. Современные CPU алгоритм требуемый для расчета контрольной суммы «перемалывают» за исчезающе малый отрезок времени. Главное что бы все необходимые данные для расчета итоговой суммы находились в памяти и их не приходилось считывать и подкачивать с диска. Но у нас по условиям задачи алгоритм включается в работу только тогда, когда все его входные данные гарантированно находятся именно там — в оперативной памяти. Вывод: CHECKSUM — наше необсуждаемое «все».

Заключение.

Ну а что же у нас с вопросом который, собственно, привел к появлению данной статьи? Насколько актуальны бэкапы, с учетом того, что режим CHECKSUM «детектирует» проблемы данных очень хорошо? Внимательным читателям ответ должен быть очевиден: с появлением в SQL Server 2005 нового режима контроля целостности данных актуальность бэкапов не изменилась ни на йоту. Поскольку обнаружение «плохих» данных — одно направление. А замена их последними достоверно известными «хорошими» данными — свое направление. Сообщения о некорректном просчете контрольной суммы важны до чрезвычайности. Ни в коем случае не игнорируйте их! В 90% случаев это надежный признак проблем с «железом», докапывайтесь до «корней» вопроса. Разумеется вашими первыми «подозреваемыми» будут HDD и его контроллер, но нельзя сбрасывать со счетов и «битые планки памяти», и прочие компоненты оборудования в зависимости от конкретной реализации вашей дисковой подсистемы. Если «виновного» в происходящем не найти, то с вероятностью близкой к 100% ошибки incorrect checksum не только не прекратятся «сами собой», а ровно наоборот — будут расти «как снежный ком». Действительно «одиночные» ошибки такого сорта встречаются очень, очень не часто. Скорей всего проблема будет «глобального» порядка и что-то менять в системе придется. Но при всем при этом вашим пользователям нужны согласованные, «не порченные» данные, даже если это будет их вариант из недавней истории. Ваш бодрый рапорт «найден bad HDD и заменен на good HDD» их максимум порадует, но в работе не поможет совершенно — качественных данных-то нет! И вот тут вам (и вашим пользователям) CHECKSUM никоим образом не помощник, он же только диагностирует проблему. А «хорошие» данные можно взять лишь в одном месте — в бэкапе. Предварительно их туда поместив, разумеется. Одним словом, «каждой задаче — свой инструмент».

Автор традиционно благодарит своих читателей за их внимание уделенное ресурсу sqlCMD.ru и желает всем качественных и быстрых дисков в сочетании с надежной стратегией резервного копирования. :) До новых встреч!

  • Другие части статьи:
  • 1
  • 2
  • вперед »