8.10.25

Boot Page и их повреждения

Автор: Paul Randal, Search Engine Q&A #20: Boot pages, and boot page corruption

Для начала: что такое загрузочная страница (boot page)? В каждой базе данных есть единственная страница, на которой хранится критически важная информация о самой базе. Это всегда страница 9 в файле 1 (первый файл в файловой группе PRIMARY). Её можно посмотреть с помощью DBCC PAGE — команда интерпретирует все поля. Есть и другая команда, DBCC DBINFO, которая тоже выдаёт всю эту информацию (фактически, код DBCC PAGE вызывает тот же внутренний код дампа). Команда недокументирована и не поддерживается, но широко известна и «задокументирована» во множестве мест в сети — и, поскольку использует тот же код, что и DBCC PAGE, по моему мнению, она столь же безопасна в использовании.

Заметьте: вывод DBCC DBINFO и DBCC PAGE для загрузочной страницы может меняться от версии к версии!

Итак, что находится на загрузочной странице?

DBCC DBINFO (‘BootPageTest’);
GO

DBINFO STRUCTURE:
DBINFO @0x5BF6EF84
dbi_dbid = 19                        dbi_status = 65536                   dbi_nextid = 2073058421
dbi_dbname = BootPageTest            dbi_maxDbTimestamp = 2000            dbi_version = 611
dbi_createVersion = 611              dbi_ESVersion = 0
dbi_nextseqnum = 1900-01-01 00:00:00.000                                  dbi_crdate = 2008-07-10 15:53:18.843
dbi_filegeneration = 0
dbi_checkptLSN
m_fSeqNo = 41                        m_blockOffset = 29                   m_slotId = 55
dbi_RebuildLogs = 0                  dbi_dbccFlags = 2
dbi_dbccLastKnownGood = 1900-01-01 00:00:00.000
dbi_dbbackupLSN
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_oldestBackupXactLSN
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_LastLogBackupTime = 1900-01-01 00:00:00.000
dbi_differentialBaseLSN
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_createIndexLSN
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_versionChangeLSN
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_familyGUID = a4e88c13-b4cf-4320-834e-92b237244d4b
dbi_recoveryForkNameStack
entry 0
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
m_guid = a4e88c13-b4cf-4320-834e-92b237244d4b
entry 1
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
m_guid = 00000000-0000-0000-0000-000000000000
dbi_differentialBaseGuid = 00000000-0000-0000-0000-000000000000           dbi_firstSysIndexes = 0001:00000014
dbi_collation = 872468488            dbi_category = 0                     dbi_maxLogSpaceUsed = 231936
dbi_localState = 0                   dbi_roleSequence = 0
dbi_failoverLsn
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_dbmRedoLsn
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_dbmOldestXactLsn
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_dbMirrorId = 00000000-0000-0000-0000-000000000000
dbi_pageUndoLsn
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_disabledSequence = 0
dbi_dvSplitPoint
m_fSeqNo = 0                         m_blockOffset = 0                    m_slotId = 0
dbi_CloneCpuCount = 0                dbi_CloneMemorySize = 0

DBCC execution completed. If DBCC printed error messages, contact your system administrator.

Там много всего интересного, например:

  • dbi_version и dbi_createversion: номер физической версии базы данных (и версия на момент создания). Объяснение см. в вопросе 1 в колонке SQL Q&A за август 2008 года в TechNet Magazine (см. здесь).
  • dbi_RebuildLogs: счётчик того, сколько раз у базы данных перестраивали журнал транзакций. Поддержка (PSS) может использовать его, чтобы понять, не вызваны ли проблемы с повреждениями тем, что администраторы пересоздавали журнал.
  • dbi_dbccLastKnownGood: время завершения последнего «чистого» запуска DBCC CHECKDB.
  • набор различных LSN, относящихся к контрольным точкам, резервным копиям, зеркалированию базы данных;
  • dbi_LastLogBackupTime: самоочевидно;
  • dbi_differentialBaseGuid: GUID, созданный последним полным резервным копированием базы данных. Дифференциальные копии можно восстанавливать только поверх соответствующего полного бэкапа — «внеплановый» полный бэкап может испортить ваш план восстановления после аварии — подробности см. в этой публикации.

А что, если эта страница повреждена? Я повредил базу BootPageTest так, чтобы загрузочная страница была испорчена. Посмотрим, что будет:

USE BootPagetest;
GO

Msg 913, Level 16, State 4, Line 1

Could not find database ID 19. Database may not be activated yet or may be in transition. 
Reissue the query once the database is available. 
If you do not think this error is due to a database that is transitioning its state and 
this error continues to occur, contact your primary support provider. 
Please have available for review the Microsoft SQL Server error log and any 
additional information relevant to the circumstances when the error occurred.

Хорошо, попробуем перевести базу в режим EMERGENCY:

ALTER DATABASE BootPageTest SET EMERGENCY;
GO

Msg 824, Level 24, State 2, Line 1

SQL Server detected a logical consistency-based I/O error: incorrect checksum 
(expected: 0xcdee22fa; actual: 0xcb6ea2fa). It occurred during a read of page (1:9) 
in database ID 19 at offset 0x00000000012000 in file 
‘C:\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\DATA\BootPageTest.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.

Хм. А если запустить DBCC CHECKDB?

DBCC CHECKDB (‘BootPageTest’) WITH NO_INFOMSGS, ALL_ERRORMSGS;
GO

Msg 922, Level 14, State 1, Line 1

Database ‘BootPageTest’ is being recovered. Waiting until recovery is finished.

Перспективы, мягко говоря, нерадостные. Очевидно, перевод в EMERGENCY завершить не удалось. Каков статус базы?

SELECT [state_desc] FROM sys.databases WHERE [name] = ‘BootPageTest’;
GO

state_desc
————————————————————
RECOVERY_PENDING

Загрузочная страница недоступна, а значит, по сути, недоступна и база данных — в данном случае именно это и означает такой статус.

К чему всё это? Если загрузочная страница повреждена, вы не сможете запустить DBCC CHECKDB — значит, не сможете выполнить repair; и вы не сможете перевести базу в EMERGENCY — значит, нельзя «вытянуть» данные в новую базу. Это означает, что НЕ СУЩЕСТВУЕТ способа восстановиться при повреждённой загрузочной странице, КРОМЕ как восстановиться из резервных копий. Ещё одна причина иметь бэкапы… 

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



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

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