При работе с базами данных 1С на платформе Microsoft SQL Server одной из самых пугающих ошибок является 824 (logical consistency-based I/O error). Она свидетельствует о том, что страница данных была физически прочитана с диска, но её контрольная сумма не совпала с той, что была записана ранее. Это явный признак повреждения данных, который требует немедленного вмешательства. В этой статье мы подробно разберем, как диагностировать эту проблему, как спасти данные и как не допустить повторения ситуации.
Прежде всего, проанализируем сообщение, которое выдает SQL Server. В нем зашифрована вся необходимая информация для локализации проблемы. Рассмотрим типичный пример:
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0x07b4c9e4; actual: 0x5e84dc0d). It occurred during a read of page (1:107359) in database ID 12 at offset 0x000000346be000 in file 'F:\Data\HRM_3_03.mdf'.
Из этого сообщения мы можем извлечь следующие данные:
Первым делом нам необходимо выяснить масштаб катастрофы. Для этого воспользуемся основной командой проверки целостности. Разберем процесс запуска диагностики через SQL Server Management Studio (SSMS):
-- Проверка базы данных без автоматического исправления
DBCC CHECKDB ('Имя_Вашей_Базы') WITH NO_INFOMSGS, ALL_ERRORMSGS;
Рассмотрим, что мы ищем в результатах. Если команда возвращает ошибки, SQL Server укажет, в каких именно объектах (таблицах или индексах) они находятся. Если ошибок мало, мы можем попытаться восстановить конкретные объекты. Если ошибок сотни — проблема носит системный характер (скорее всего, умирает диск или RAID-контроллер).
Вместо того чтобы сразу удалять данные, выясним, какая именно таблица 1С пострадала. Зная номер страницы из текста ошибки (например, 1:107359), мы можем запустить специальный запрос. Проанализируем соответствие страницы объекту:
SELECT
p.partition_id,
object_name(p.object_id) AS TableName,
i.name AS IndexName,
au.type_desc AS AllocationUnitType
FROM sys.allocation_units au
JOIN sys.partitions p ON au.container_id = p.hobt_id
JOIN sys.indexes i ON p.object_id = i.object_id AND p.index_id = i.index_id
WHERE au.first_page = 0x -- здесь может потребоваться более сложный запрос через DBCC PAGE
Более простым способом будет использование недокументированной команды DBCC PAGE. Это позволит нам точно увидеть, к какой таблице 1С относится "битый" блок. Если поврежден индекс, мы легко вылечим базу обычным перестроением индексов (Reindex). Если же повреждена таблица данных, ситуация сложнее — часть записей (например, проводок или документов) может быть безвозвратно потеряна.
Рассмотрим три основных пути решения проблемы, от безопасных к рискованным:
Как показывает практика (и случай в обсуждаемой теме), часто проблема кроется в физическом сбое дискового массива или кэша RAID-контроллера. Разберем последовательность действий:
CONTINUE_AFTER_ERROR, но лучше иметь актуальный бэкап до сбоя).DBCC CHECKDB. Если ошибки исчезли — проблема была в старых дисках. Если остались — повреждение уже "зацементировалось" в данных.Если ваша база работает в модели восстановления FULL и у вас есть цепочка бэкапов, вы можете выполнить точечную операцию. Это профессиональный метод, позволяющий "заплатать дыру" в живой базе, не откатывая её целиком на вчерашний день.
RESTORE DATABASE [Имя_Базы]
PAGE = '1:107359'
FROM DISK = 'C:\Backup\FullBackup.bak'
WITH NORECOVERY;
-- Затем последовательно накатываем логи транзакций
Это крайняя мера. Команда просто удалит поврежденные страницы, чтобы вернуть базе структурную целостность. Проанализируем последствия: данные, которые находились на странице 1:107359, будут стерты. В 1С это может привести к появлению "объектов не найдено" или нарушению ссылочной целостности.
-- Перевод базы в однопользовательский режим
ALTER DATABASE [Имя_Базы] SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
-- Попытка исправления с потерей данных
DBCC CHECKDB ('Имя_Базы', REPAIR_ALLOW_DATA_LOSS);
GO
-- Возврат в многопользовательский режим
ALTER DATABASE [Имя_Базы] SET MULTI_USER;
GO
Выясним, почему бэкапы автора темы оказались бесполезными. По умолчанию стандартный бэкап не проверяет контрольные суммы. Если страница на диске уже была битой, SQL просто скопировал её в файл .bak. Чтобы этого избежать, всегда используем параметр CHECKSUM.
Рассмотрим пример правильного скрипта резервного копирования:
BACKUP DATABASE [HRM_3_03]
TO DISK = 'F:\Backups\HRM_Full.bak'
WITH CHECKSUM, VERIFYONLY;
Параметр WITH CHECKSUM заставит SQL Server проверить каждую страницу в процессе копирования. Если обнаружится ошибка 824, создание бэкапа прервется, и вы узнаете о проблеме в тот же день, а не спустя неделю.
Проанализируем критически важную настройку базы данных — PAGE_VERIFY. Для всех баз 1С она должна находиться в режиме CHECKSUM. Проверим это запросом:
SELECT name, page_verify_option_desc
FROM sys.databases
WHERE name = 'Имя_Вашей_Базы';
Если вы видите значение TORN_PAGE_DETECTION или NONE, немедленно измените его:
ALTER DATABASE [Имя_Базы] SET PAGE_VERIFY CHECKSUM;
Ошибка 824 — это серьезный сигнал о неисправности оборудования. Если перенос базы на другой сервер решил проблему, значит, старая дисковая подсистема подлежит замене. Однако помните: после любого восстановления или переноса "битой" базы необходимо выполнить полную проверку DBCC CHECKDB, чтобы убедиться, что логические связи внутри 1С не нарушены.