Как исправить ошибку ввода-вывода и повреждение контрольной суммы страницы в MS SQL Server при работе с 1С?

Системный администратор 1С v8.3 (Управляемые формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При обслуживании или выгрузке информационной базы 1С в файл .dt администраторы нередко сталкиваются с критическим сбоем СУБД: «SQL Server обнаружил логическую ошибку ввода-вывода, связанную с согласованностью: неправильная контрольная сумма» (ошибка 824, HRESULT=80004005). При этом стандартная процедура восстановления средствами DBCC CHECKDB завершается аварийно с сообщением 8921 («В процессе сбора фактов была обнаружена ошибка»), а прямые команды очистки или удаления сбойных таблиц блокируются СУБД. Разберем по шагам, почему возникает эта проблема, как локализовать поврежденные таблицы и какие способы позволяют восстановить работоспособность базы данных 1С.

Выясним причину возникновения ошибки 824

Ошибка с кодом 824 означает, что страница данных была прочитана с диска, но ее фактическая контрольная сумма не совпала со значением, рассчитанным СУБД при последней записи. Проанализируем ключевые факторы, приводящие к такому состоянию:

  1. Аппаратные сбои контроллеров и накопителей. В программных или встроенных RAID-массивах (например, Intel RST / HostRAID) отсутствует энергонезависимая память с батарейным питанием (BBU). Микросбои питания или зависания ОС приводят к частичной записи блоков (torn pages).
  2. Сбои оперативной памяти (RAM). Если в сервере используется память без поддержки коррекции ошибок (ECC), искажение байтов может происходить прямо в оперативной памяти перед отправкой страницы подсистеме ввода-вывода.
  3. Сторонние драйверы-фильтры. Антивирусное ПО или некорректно работающие драйверы моментальных снимков (VSS), перехватывающие ввод-вывод к файлам .mdf и .ndf, могут нарушать целостность страниц.

Шаг 1. Локализация поврежденных таблиц средствами T-SQL

Когда общая проверка базы прерывается из-за сбоя в механизме сбора фактов, необходимо выяснить, в каких именно физических таблицах находятся сбойные страницы. Для этого последовательно переберем все таблицы схемы базы данных простым счетным запросом. Рассмотрим скрипт, автоматизирующий данный поиск:


USE ZUP;
GO
DECLARE @SchemaName NVARCHAR(MAX);
DECLARE @TableName NVARCHAR(MAX);
DECLARE @SqlCommand NVARCHAR(MAX);

DECLARE TableCursor CURSOR LOCAL FAST_FORWARD FOR 
SELECT s.name, t.name 
FROM sys.tables t 
INNER JOIN sys.schemas s ON t.schema_id = s.schema_id;

OPEN TableCursor;
FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName;

WHILE @@FETCH_STATUS = 0 
BEGIN
    PRINT @TableName;
    SET @SqlCommand = N'SELECT COUNT(*) FROM ' + QUOTENAME(@SchemaName) + '.' + QUOTENAME(@TableName);
    EXEC sys.sp_executesql @SqlCommand;
    FETCH NEXT FROM TableCursor INTO @SchemaName, @TableName;
END

CLOSE TableCursor;
DEALLOCATE TableCursor;

Таблица, на которой скрипт прерывается с ошибкой 824, и содержит поврежденную страницу. Обратите внимание: имя таблицы в СУБД (например, _Reference418) соответствует определенному объекту метаданных 1С (например, Справочник.ПризПодарокПрисоединенныеФайлы). Соответствие имен таблиц объектам метаданных можно определить с помощью метода платформы ПолучитьСтруктуруХраненияБазыДанных().

Если прямой подсчет строк через COUNT(*) падает, оценить реальный объем данных в поврежденном объекте можно без физического чтения сбойных страниц — через системные динамические представления:


SELECT t.name AS table_name, p.rows AS row_count 
FROM sys.tables t 
JOIN sys.partitions p ON t.object_id = p.object_id 
WHERE t.name = '_Reference418' AND p.index_id IN (0, 1);

Шаг 2. Варианты восстановления на уровне СУБД

Разберем методы реанимации данных, доступные на уровне SQL Server:

  1. Точечное восстановление страниц (Page Restore). Если в базе настроена полная модель восстановления (FULL) и непрерывный бэкап журналов транзакций, поврежденную страницу (например, 1:89376) можно поднять точечно из архивной копии с накатом транзакций командой RESTORE DATABASE ZUP PAGE = '1:89376' FROM DISK = '...' WITH NORECOVERY.
  2. Перевод базы в аварийный режим перед ремонтом. Если DBCC CHECKTABLE ('имя_таблицы', REPAIR_ALLOW_DATA_LOSS) или TRUNCATE TABLE выдают ошибку, необходимо перевести базу в режим EMERGENCY и SINGLE_USER. В этом состоянии СУБД отключает часть внутренних проверок метаданных, что позволяет изолировать или очистить сбойную аллокацию:
    
    ALTER DATABASE ZUP SET EMERGENCY;
    ALTER DATABASE ZUP SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
    DBCC CHECKTABLE ('_Reference418', REPAIR_ALLOW_DATA_LOSS);
    ALTER DATABASE ZUP SET MULTI_USER;
    ALTER DATABASE ZUP SET ONLINE;
    
  3. Построчное чтение уцелевших записей. Если в таблице есть ценные данные, можно обойти битую страницу физически, отфильтровав выборку по функции sys.fn_PhysLocFormatter(%%physloc%%), исключив блок с адресом поврежденной страницы.

Шаг 3. Восстановление через перенос таблиц (SSMS Import/Export Wizard)

Если восстановить поврежденную страницу не удается, а поврежденный объект не содержит критически важных уникальных записей (или эти данные можно взять из старой резервной копии), наиболее надежным практическим выходом является селективный перенос таблиц:

  1. Разворачиваем пустую целевую базу данных на стабильном дисковом массиве.
  2. С помощью мастера экспорта и импорта данных SQL Server Management Studio (SSMS Import and Export Wizard) переносим все неповрежденные таблицы из сбойной базы в новую.
  3. Поврежденные таблицы импортируем из предыдущего небитого бэкапа (например, двухнедельной давности).
  4. Запускаем технологический процесс «Тестирование и исправление информационной базы» (ТиИ) в конфигураторе 1С с установленными флагами «Проверка логической целостности» и «Реструктуризация таблиц информационной базы». При обнаружении отсутствующих ссылок платформа создаст служебные объекты «Объект не найден» или очистит «битые» ссылки в зависимости от выбранных настроек.

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

После успешной сборки таблиц и выполнения ТиИ администраторы часто замечают, что файл выгрузки .dt и сам файл данных .mdf весят существенно меньше оригинала (например, размер дампа падает с 1.7 ГБ до 450 МБ). Разберем, почему это происходит:

  1. Устранение фрагментации и сжатие индексов. Если на сервере долгое время не выполнялось регламентное обслуживание (дефрагментация и перестроение индексов REBUILD / REORGANIZE), таблицы базы 1С могут раздуваться в два и более раз из-за особенностей генерации GUID в кластерных индексах. При выгрузке в .dt индексы не выгружаются вовсе, а при реструктуризации они строятся заново без пустого зарезервированного пространства.
  2. Таблицы длинных данных (LOB). Если поврежденная таблица относилась к справочникам присоединенных файлов (например, Справочник.ПризПодарокПрисоединенныеФайлы), а двоичные данные сканов и документов хранились внутри СУБД, потеря или сброс этой таблицы закономерно снижает общий вес базы. Обязательно сверьте количество записей и целостность прикрепленных файлов в интерфейсе программы.
← На главную