Как восстановить базу 1С на SQL Server при ошибке ввода-вывода (Error 1117) и повреждении диска?

Системный администратор
← На главную

Ситуация, когда серверная база 1С перестает делать бэкапы, а стандартные средства SQL Server, такие как DBCC CHECKDB, зависают или аварийно завершаются, является критической. Если при этом в логах SQL Server появляется ошибка 1117 (Запрос не был выполнен из-за ошибки ввода/вывода на устройстве), это однозначно указывает на физическое повреждение поверхности жесткого диска или деградацию RAID-массива. В данной статье мы разберем по шагам, как действовать в такой ситуации, когда обычное копирование файла mdf невозможно, а сроки восстановления поджимают.

Анализ ситуации и диагностика ошибки

Прежде всего, проанализируем системные логи. Ошибка 1117 — это ответ операционной системы, который означает, что контроллер диска не смог прочитать данные из определенного сектора. Рассмотрим типичное сообщение из лога SQL Server:

A read of the file 'D:\SQL\DATA\buh_fok.mdf' at offset 0x00000362af6000 succeeded after failing 1 time(s) with error: 1117

Это сообщение говорит о том, что SQL Server столкнулся с «битым» блоком данных. Если DBCC CHECKDB с параметром REPAIR_ALLOW_DATA_LOSS прерывается или вызывает падение службы SQL, значит, повреждение затронуло критические системные таблицы базы данных или дерево метаданных. В таком состоянии стандартные механизмы восстановления SQL бессильны, так как они не могут даже прочитать структуру базы для ее исправления.

Шаг 1. Попытка создания физической копии файла данных

Поскольку оригинальный файл mdf заблокирован или не копируется обычными средствами Windows (процесс зависает на определенном проценте), нам необходимо создать его копию, игнорируя нечитаемые сектора. Никогда не проводите эксперименты над оригинальным поврежденным файлом!

Рассмотрим вариант использования специализированных утилит, которые умеют «пропускать» ошибки чтения, заполняя нечитаемые места нулями. Это позволит нам получить файл, который SQL Server сможет хотя бы «приаттачить» (подключить).

  1. Остановите службу SQL Server, чтобы освободить дескрипторы файлов.
  2. Воспользуйтесь утилитой типа Unstoppable Copier или FastCopy (включив опцию Ignore errors).
  3. Если у вас есть доступ к среде Linux, можно использовать мощную команду dd, которая идеально подходит для таких задач:

# dd if=/dev/sda/path_to_base/baza.mdf of=/dev/sdb/copy_baza.mdf conv=sync,noerror bs=4k status=progress

Разберем параметры этой команды: noerror заставляет программу продолжать работу при ошибках чтения, а conv=sync заполняет нечитаемые блоки нулями, чтобы сохранить смещение (offset) всех последующих данных. Это критически важно для структуры mdf.

Шаг 2. Подключение копии и логическое восстановление

После того как вы получили «дырявую», но физически целостную копию файла на другом исправном диске, попробуем вернуть базу в рабочее состояние. Выясним, насколько серьезны потери. Подключите полученный файл к SQL Server.

Если база данных при подключении переходит в режим RECOVERY_PENDING или SUSPECT, переведите ее в аварийный режим и попробуйте выполнить восстановление:


ALTER DATABASE "myDBname" SET EMERGENCY;
GO
ALTER DATABASE "myDBname" SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
GO
DBCC CHECKDB ('myDBname', REPAIR_ALLOW_DATA_LOSS);
GO
ALTER DATABASE "myDBname" SET MULTI_USER;
GO

Важный момент: использование REPAIR_ALLOW_DATA_LOSS на исправном диске с копией файла пройдет гораздо быстрее и, скорее всего, не вызовет падения службы, так как физических ошибок чтения (1117) больше не будет. SQL Server просто удалит поврежденные страницы данных.

Шаг 3. Потабличное спасение данных (Manual Data Extraction)

Если база данных подключилась, но CHECKDB все равно не справляется или 1С не запускается, проанализируем возможность ручного выгрузки данных. Часто повреждения приходятся на таблицы индексов или итогов, которые можно пересчитать, но иногда страдают и таблицы с документами.

Рассмотрим стратегию переноса данных в новую чистую базу той же конфигурации:

  1. Создайте новую пустую базу в 1С (с идентичной конфигурацией).
  2. Используйте SQL-скрипты для переноса данных из «битой» базы в новую.

Пример запроса для переноса данных одной таблицы:

INSERT INTO NewDB.dbo._InfoRg1234 SELECT * FROM OldDB.dbo._InfoRg1234;

Проанализируем этот процесс: если при выполнении INSERT SQL Server выдает ошибку на конкретной таблице, значит, именно в ней находятся поврежденные данные. В этом случае мы можем попытаться выгрузить данные частями, обходя поврежденную страницу, используя фильтрацию по первичному ключу или другим полям.

Шаг 4. Локализация поврежденной таблицы по Offset

Выясним, какая именно таблица 1С пострадала, используя данные из лога. В SQL Server размер страницы всегда равен 8 КБ (8192 байта). Возьмем offset из лога (например, 0x00000362af6000), переведем его в десятичный вид и разделим на 8192.

Зная номер страницы, мы можем выполнить команду:

DBCC PAGE ('имя_базы', 1, номер_страницы, 3);

В выводе этой команды в поле Metadata: ObjectId будет указан ID объекта. Выполнив запрос SELECT OBJECT_NAME(ID_объекта), мы узнаем имя таблицы 1С. Если это индекс (имя начинается с _DocumentL... или заканчивается на _idx), его можно просто пересоздать через консоль SQL или реиндексацию в конфигураторе 1С, что полностью решит проблему без потери данных.

Итоговые рекомендации

Подводя итог, проанализируем последовательность действий при возникновении ошибки 1117:

Помните, что после восстановления базы методом REPAIR_ALLOW_DATA_LOSS необходимо обязательно выполнить Тестирование и исправление (ТиИ) в конфигураторе 1С, так как SQL Server восстанавливает физическую целостность страниц, но может нарушить логические связи между таблицами 1С.

← На главную