При эксплуатации баз данных 1С:Предприятие на платформе MS SQL Server администраторы могут столкнуться с критическими ошибками, связанными с целостностью данных на физическом уровне, в диагностике которых поможет анализ SQL сервера глазами 1С-ника. Одной из самых неприятных является ошибка контрольной суммы (Checksum error) или logical consistency-based I/O error. В данной статье мы подробно разберем, как диагностировать такие проблемы, какие таблицы можно безопасно очистить, а какие требуют аккуратного восстановления из копии, и как правильно выполнять эти операции средствами T-SQL.
Когда SQL Server читает страницу данных с диска, он сверяет контрольную сумму, записанную в заголовке страницы, с тем, что фактически считано. Если значения не совпадают, возникает ошибка:
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0x...; actual: 0x...).
It occurred during a read of page (...) in database ID ... in file ...
Это однозначно указывает на повреждение файла базы данных (MDF) или журнала транзакций (LDF). Причинами чаще всего служат сбои дисковой подсистемы, RAID-контроллера или некорректное выключение сервера. В контексте 1С это проявляется как невозможность провести документ, сформировать отчет или выполнить "Тестирование и исправление" (ТИИ) — процесс прерывается на определенной таблице.
Первым шагом мы должны определить масштаб повреждений. Для этого используем команду проверки целостности базы данных:
DBCC CHECKDB ('ИмяВашейБазы') WITH NO_INFOMSGS;
Результат выполнения покажет список поврежденных таблиц. В 1С таблицы имеют специфические имена, например _Reference93 или AccumRgChngR10196. Нам необходимо сопоставить эти имена с объектами метаданных 1С (Справочники, Документы, Регистры), используя функцию ПолучитьСтруктуруХраненияБазыДанных() в 1С или просмотрев системные таблицы, если доступ к 1С невозможен.
Часто поврежденными оказываются таблицы с именами, начинающимися на AccumRgChngR..., DocumentChngR... и подобные. Это таблицы регистрации изменений для планов обмена. Если у вас настроена синхронизация (РИБ или обмен с другими системами), эти таблицы хранят указатели на измененные объекты, которые нужно передать.
Важный момент: Данные в этих таблицах являются служебными. Их потеря приведет лишь к тому, что изменения не уйдут в обмен автоматически, и потребуется полная регистрация данных для узла обмена. Сами бизнес-данные (документы, справочники) здесь не хранятся.
Если DBCC CHECKDB указывает на такую таблицу, мы можем безопасно очистить её. Рассмотрим, как это сделать:
DELETE, и меньше нагружает журнал транзакций.
TRUNCATE TABLE [ИмяБазы].[dbo].[_AccumRgChngR10196];
После выполнения этой команды таблица будет пустой и физически корректной (создадутся новые пустые страницы). Далее в режиме 1С:Предприятие необходимо зайти в настройки плана обмена и выполнить перерегистрацию данных для узлов, чтобы обмен прошел корректно — для этого подойдёт обработка управления регистрацией изменений на планах обмена.
Сложнее обстоит дело, если повреждены основные таблицы данных, например _Reference93 (Справочник.Склады) или _Document252 (Документ.СчетНаОплату). Просто удалить и создать их заново в 1С нельзя.
Разберем, почему нельзя просто пересоздать данные руками:
СправочникСсылка, ДокументСсылка) уникальна и хранится в поле _IDRRef в формате GUID.<Объект не найден...>.Поэтому единственно верный путь — восстановить таблицу с сохранением идентификаторов _IDRRef. Если у нас есть резервная копия (пусть даже не самая свежая), мы можем перенести данные оттуда.
Предположим, у нас есть "битая" таблица _Reference93 в рабочей базе Base_Work и целая таблица в копии Base_Copy.
Рассмотрим алгоритм действий:
Шаг 1. Очистка поврежденной таблицы
Сначала пробуем очистить текущую таблицу. Если степень повреждения позволяет, команда сработает:
TRUNCATE TABLE [Base_Work].[dbo].[_Reference93];
Если таблица повреждена настолько, что даже TRUNCATE не проходит, может потребоваться удаление таблицы (DROP TABLE) и воссоздание её структуры (скрипт CREATE TABLE можно сгенерировать из копии базы).
Шаг 2. Перенос данных
Теперь вставим данные из копии. Если обе базы находятся на одном SQL Server, мы можем сделать это одним запросом:
INSERT INTO [Base_Work].[dbo].[_Reference93]
SELECT * FROM [Base_Copy].[dbo].[_Reference93];
Этот запрос скопирует все поля, включая критически важный _IDRRef. После этой операции 1С "узнает" свои склады, и битых ссылок не будет. Если базы на разных серверах, можно использовать механизм Linked Server или выгрузку/загрузку через мастер Import/Export Data в SSMS.
Внимание: Если с момента создания копии в рабочей базе создавались новые элементы справочников, они, к сожалению, будут утеряны при таком способе восстановления, так как их нет в копии — выявить расхождения поможет обработка сравнения данных между базами 1С. Их придется вводить вручную или использовать поиск битых ссылок и создание из них объектов, но "старый" костяк данных будет спасен.
Регистры накопления и бухгалтерии в SQL Server физически хранятся в нескольких таблицах. Обычно это:
Таблицы итогов часто имеют имена с суффиксами или префиксами, отличными от основной таблицы. Например, для регистра бухгалтерии это может быть AccRgAT... (Итоги по счетам) или AccRgED... (Итоги по проводкам, если включено разделение итогов).
Если DBCC CHECKDB показывает ошибку именно в таблице итогов, ситуация благоприятная. Таблицы итогов являются вычисляемыми. Это значит, что их можно полностью очистить, а затем заставить 1С рассчитать их заново на основании таблицы движений.
Разберем процедуру восстановления таблиц итогов:
Очистка таблицы в SQL
Находим имя таблицы итогов, на которую ругается проверка (например, AccRgAT1593). Выполняем очистку:
TRUNCATE TABLE [Base_Work].[dbo].[AccRgAT1593];
После этого, если зайти в 1С, отчеты (например, ОСВ) будут показывать нули или некорректные данные, но база будет работать.
Пересчет итогов в Конфигураторе
Запускаем конфигуратор 1С. Переходим в меню Администрирование -> Тестирование и исправление.
Устанавливаем только одну галочку: Пересчет итогов. Выбираем переключатель "Для всех регистров" или, если мы точно знаем, какому регистру принадлежит таблица, можно выбрать конкретные регистры (хотя безопаснее пересчитать всё).
Выполнение пересчета
Нажимаем "Выполнить". Процесс может занять длительное время (от минут до часов в зависимости от объема базы). В это время 1С прочитает таблицу движений (которая должна быть целой) и заново заполнит очищенную нами таблицу AccRgAT... в SQL Server актуальными цифрами.
Если у вас нет резервной копии, а повреждения затронули таблицы движений или уникальных ссылочных данных, последним средством является встроенный механизм починки SQL Server.
ALTER DATABASE [Base_Work] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DBCC CHECKDB ('Base_Work', REPAIR_ALLOW_DATA_LOSS);
ALTER DATABASE [Base_Work] SET MULTI_USER;
Проанализируем риски этого метода:
Использовать этот метод следует только тогда, когда стоит вопрос "спасти хоть что-то" и нет никаких бэкапов. После применения REPAIR_ALLOW_DATA_LOSS обязательно требуется запуск полного "Тестирования и исправления" в 1С с проверкой логической целостности.
Восстановление базы при повреждении checksum — это борьба с последствиями аппаратных сбоев. Мы выяснили, что:
AccumRgChng...) можно смело очищать (truncate).AccRgAT..., AccumRgT...) можно очищать в SQL с последующим пересчетом итогов в Конфигураторе.INSERT) данных из бэкапа для сохранения GUID (_IDRRef).