Внезапное отключение электроэнергии на сервере — страшный сон любого системного администратора и разработчика 1С. Подобные инциденты часто приводят к аппаратным сбоям, рассинхронизации кэша записи дисков и, как следствие, к повреждению структуры базы данных на уровне СУБД. Одним из наиболее неприятных последствий является появление ошибки HRESULT=80004005 SQLSTATE=HY000 Ошибка СУБД: Страница... помечена RestorePending, что может означать повреждение диска.
В этой статье мы подробно разберем природу данной ошибки, проанализируем лог утилиты DBCC CHECKDB, выясним, почему стандартные тесты дисков могут не показывать проблем, а также изучим пошаговое руководство по восстановлению резервной копии в новую базу-копию с помощью T-SQL скриптов в обход ошибок монопольного доступа.
Вместе с вами мы пройдем весь путь спасения данных — от диагностики до успешного развертывания рабочей копии базы.
---
Для начала выясним причину возникновения ошибки. Ошибка с кодом HRESULT=80004005 является общим системным сбоем (Unspecified Error), но в контексте MS SQL Server она сопровождается конкретным состоянием страницы базы данных — RestorePending (в терминологии SQL Server это ошибка 829).
База данных MS SQL физически состоит из страниц объемом 8 КБ. Когда СУБД производит чтение или запись, она оперирует именно этими страницами. Если в момент записи данных на диск происходит аварийное отключение питания, процесс прерывается на полуслове. Это явление называется Torn Write (незавершенная или "разорванная" запись).
При последующем обращении к такой странице SQL Server обнаруживает несоответствие контрольных сумм заголовка страницы и ее тела. Чтобы защитить целостность всей остальной базы, СУБД блокирует эту конкретную поврежденную страницу, присваивая ей статус "Ожидание восстановления" (RestorePending).
Важная особенность: в отличие от аварийного режима всей базы данных (SUSPECT), при повреждении отдельных страниц база данных в целом остается в режиме ONLINE. Пользователи могут продолжать работать с другими документами и справочниками. Но как только платформа 1С или регламентное задание попытается обратиться к объекту, данные которого расположены на этой заблокированной странице, СУБД мгновенно вернет ошибку RestorePending и прервет транзакцию.
---
Зачастую администраторы сомневаются в необходимости замены накопителей, утверждая, что "стандартные тесты дисков ошибок не выявили". Давайте проанализируем фрагменты лога DBCC CHECKDB из нашей практической ситуации, чтобы понять всю серьезность положения:
---
Перейдем к решению практической задачи. Автор темы столкнулся с классической проблемой: при попытке восстановить рабочую базу из бэкапа в базу-копию (чтобы не затереть оригинал и провести аудит данных) СУБД выдает ошибку монопольного доступа и сообщает о несовпадении реквизитов (путей размещения файлов).
Разберем, почему это происходит. По умолчанию, при запуске стандартного мастера восстановления в среде SSMS (SQL Server Management Studio), СУБД пытается восстановить файлы данных (.mdf) и лога транзакций (.ldf) по тем путям и с теми именами, которые прописаны внутри самого файла бэкапа (то есть в папки оригинальной рабочей базы). Поскольку оригинальная база в этот момент запущена и файлы заняты, СУБД блокирует операцию.
Мы решим эту задачу красиво и профессионально — с помощью структурированных SQL-запросов. Этот метод работает быстрее, не требует перезапуска служб и полностью исключает человеческий фактор при работе в графическом интерфейсе.
Прежде чем перенаправить файлы восстанавливаемой базы в новое место, нам необходимо узнать их внутренние логические имена. Они могут не совпадать с физическими именами файлов на диске. Выполним следующий запрос:
RESTORE FILELISTONLY
FROM DISK = N'C:\Backup\work_db.bak';
Проанализируем результат выполнения этого запроса. Нам важна колонка LogicalName. Обычно там содержатся две строки:
work_db).work_db_log).Запишем или скопируем эти имена — они понадобятся нам на Шаге 3.
Если база-получатель (копия, которую мы назвали, например, work_db_copy) уже создана на сервере, к ней могут быть подключены фоновые процессы, консоль администрирования 1С или сеансы пользователей. Чтобы принудительно разорвать все соединения и перевести базу в монопольный режим, выполним запрос:
USE [master];
ALTER DATABASE [work_db_copy]
SET SINGLE_USER
WITH ROLLBACK IMMEDIATE;
Параметр ROLLBACK IMMEDIATE мгновенно откатит все незавершенные транзакции активных пользователей и закроет их соединения, обеспечив нам полный эксклюзивный доступ к базе.
Теперь выполним основную операцию восстановления. С помощью конструкции MOVE мы переопределим пути физического сохранения файлов .mdf и .ldf, чтобы они не конфликтовали с работающей продакшн-базой. Также мы добавим параметр REPLACE, который разрешает перезаписать существующую базу-копию:
RESTORE DATABASE [work_db_copy]
FROM DISK = N'C:\Backup\work_db.bak'
WITH
MOVE N'work_db' TO N'C:\SQLData\work_db_copy.mdf',
MOVE N'work_db_log' TO N'C:\SQLData\work_db_copy_log.ldf',
REPLACE,
RECOVERY;
Разберем подробнее ключевые параметры этого скрипта:
MOVE N'work_db' TO N'...' — указывает СУБД взять логический файл данных work_db из бэкапа и физически сохранить его по новому пути с новым именем work_db_copy.mdf.REPLACE — указывает затереть целевую базу данных work_db_copy, даже если ее структура не совпадает с бэкапом.RECOVERY — переводит базу данных в рабочее состояние (ONLINE) сразу после окончания процесса восстановления, позволяя пользователям и платформе 1С мгновенно начать работу.После успешного завершения восстановления нам необходимо вернуть базу данных из монопольного режима в штатный многопользовательский, иначе никто, кроме первого подключившегося процесса, не сможет зайти в систему:
ALTER DATABASE [work_db_copy]
SET MULTI_USER;
Поздравляем! База данных успешно восстановлена в копию под новым именем и полностью готова к работе.
---
Давайте проанализируем конкретные таблицы 1С, которые пострадали согласно логу утилиты DBCC CHECKDB:
_AccumRgOpt24664, _AccumRgOpt24665 — это таблицы настроек и статических итогов регистров накопления. Если повреждены только они, это полбеды. Их можно восстановить средствами самой платформы 1С через операцию "Пересчет итогов" в конфигураторе или через тестирование и исправление._Enum27057, _Enum27058 — системные таблицы перечислений 1С. Повреждение этих таблиц критично для ссылочной целостности конфигурации._Reference152 — физическая таблица одного из справочников 1С (например, Контрагенты, Номенклатура или Физические лица).Почему нельзя использовать автоматическое лечение DBCC CHECKDB с флагом REPAIR_ALLOW_DATA_LOSS?
Многие администраторы совершают фатальную ошибку, пытаясь выполнить команду DBCC CHECKDB ('db', REPAIR_ALLOW_DATA_LOSS) на живой базе. Само название параметра ("разрешить потерю данных") говорит о том, что SQL Server просто удалит поврежденные 8-килобайтные страницы вместе со всеми записями, которые на них находились.
В контексте СУБД база станет "здоровой", но в контексте прикладного решения 1С это обернется катастрофой: удаление страниц в таблице справочника _Reference152 приведет к появлению сотен битых ссылок вида "<Объект не найден>..." в связанных документах и регистрах. База превратится в "решето", восстановить логику учета в которой будет невероятно сложно.
Именно поэтому решение автора форума отказаться от попыток "лечения" поврежденной базы и полностью восстановить ее из актуального чистого бэкапа является единственным методологически верным и безопасным решением для непрерывности бизнеса.