Если проверка базы 1С нашла ошибки, начинать стоит с восстановления из копии. Разбираем синтаксис DBCC CHECKDB, что делает каждый из ключей REPAIR и случай 2019 года, где хорошей копии не нашлось.
Если 1С перестала проводить документы и сообщает о проблемах с согласованностью базы, сделайте бэкап текущего состояния и запустите проверку целостности на стороне SQL Server. DBCC CHECKDB — это команда Transact-SQL, которая проверяет логическую и физическую целостность всех объектов указанной базы данных Microsoft SQL Server. База 1С для SQL Server — такая же база, как любая другая, и проверяется тем же запросом: DBCC CHECKDB(N'имя_базы') WITH NO_INFOMSGS.
Трудное начинается после того, как проверка вернула ошибки согласованности. Ниже — порядок действий: где читать результат, чем лечить базу сначала и когда доходит черёд до трёх ключей REPAIR_*. Ключи эти — крайнее средство. В нашем инциденте 2019 года REPAIR_REBUILD не изменил ничего, а REPAIR_ALLOW_DATA_LOSS устранил 85 ошибок из 2603 и встал.
Коротко
- DBCC CHECKDB проверяет логическую и физическую целостность всех объектов базы данных и включает в себя
DBCC CHECKALLOC,DBCC CHECKTABLEпо каждой таблице и представлению иDBCC CHECKCATALOG. Отдельно эти три команды запускать не нужно. - Минимальный запуск для базы 1С:
DBCC CHECKDB(N'имя_базы') WITH NO_INFOMSGS. С ключомNO_INFOMSGSинформационных сообщений в выводе не будет. - Чтобы применить любой из трёх ключей
REPAIR_*, базу нужно перевести в однопользовательский режим. - Основной путь при найденных ошибках — восстановление из последней известной хорошей резервной копии.
REPAIR_ALLOW_DATA_LOSS— аварийное крайнее средство на случай, когда восстановиться из копии невозможно. - В нашем инциденте 2019 года проверка нашла 2603 ошибки согласованности.
REPAIR_REBUILDрезультат не изменил,REPAIR_ALLOW_DATA_LOSSдовёл счёт до 2518 и встал. Помогла очистка проблемной таблицы регистра — операция с потерей данных, которую мы приводим как факт инцидента, а не как рекомендацию; через час ошибка вернулась, и базу вылечило тестирование и исправление в конфигураторе 1С. Этот прогон необратим, поэтому перед ним стоит сделать резервную выгрузку информационной базы.
Что именно проверяет DBCC CHECKDB
За один запуск DBCC CHECKDB проходит по всем объектам базы и проверяет их целостность, логическую и физическую. Внутри него идёт несколько проверок: DBCC CHECKALLOC по базе, DBCC CHECKTABLE по каждой таблице и каждому представлению, DBCC CHECKCATALOG по базе, проверка каждого индексированного представления, проверка согласованности FILESTREAM на уровне ссылок и проверка данных Service Broker. Поэтому запускать DBCC CHECKALLOC, DBCC CHECKTABLE и DBCC CHECKCATALOG отдельно от CHECKDB незачем.
Права нужны такие: членство в фиксированной серверной роли sysadmin или в фиксированной роли базы данных db_owner.
Синтаксис DBCC CHECKDB
Полный синтаксис команды:
DBCC CHECKDB
[ [ ( database_name | database_id | 0
[ , NOINDEX
| , { REPAIR_ALLOW_DATA_LOSS | REPAIR_FAST | REPAIR_REBUILD } ]
) ]
[ WITH
{
[ ALL_ERRORMSGS ]
[ , EXTENDED_LOGICAL_CHECKS ]
[ , NO_INFOMSGS ]
[ , TABLOCK ]
[ , ESTIMATEONLY ]
[ , { PHYSICAL_ONLY | DATA_PURITY } ]
[ , MAXDOP = number_of_processors ]
}
]
]
Из всего набора для первой проверки базы 1С нужны имя базы и один-два параметра после WITH. Три параметра — NO_INFOMSGS, PHYSICAL_ONLY и DATA_PURITY — меняют то, что вы увидите в выводе, сколько проверка идёт и что именно она проверит; разбираю их отдельно.
NO_INFOMSGS: короткий вывод вместо простыни
NO_INFOMSGS убирает из вывода информационные сообщения, все до одного. Без него команда печатает многострочный отчёт DBCC results for '<object>'… по каждому объекту базы и заканчивает строкой CHECKDB found 0 allocation errors and 0 consistency errors in database '<db>'. вместе с DBCC execution completed. If DBCC printed error messages, contact your system administrator. С NO_INFOMSGS на чистой базе вы увидите только The command(s) completed successfully., а ошибки, если они есть, напечатаются отдельно. Читать отчёт по каждому объекту базы 1С глазами я не готов, поэтому запускаю проверку сразу с этим ключом.
PHYSICAL_ONLY: облегчённая проверка для регулярных прогонов
PHYSICAL_ONLY ограничивает проверку физической структурой страниц и заголовков записей плюс согласованностью выделения места. На больших базах это может намного сократить время работы CHECKDB. Для частых запусков на продуктивной системе берите именно этот вариант, а полный прогон DBCC CHECKDB всё равно делайте периодически.
Три ограничения при этом надо знать заранее. PHYSICAL_ONLY всегда подразумевает NO_INFOMSGS и не допускается ни с одним из ключей восстановления. Все проверки данных FILESTREAM он пропускает. И проверки целостности значений столбцов при нём не выполняются вовсе.
Что молчит в базе, переехавшей со старых версий SQL Server
DATA_PURITY заставляет CHECKDB искать значения столбцов вне допустимого диапазона: например, дату и время за пределами того, что принимает тип datetime, или столбцы decimal с некорректной точностью. В обычной базе эти проверки включены по умолчанию и параметра не требуют. Исключение — базы, обновлённые с более ранних версий SQL Server. У них проверки значений столбцов по умолчанию выключены, пока DBCC CHECKDB WITH DATA_PURITY не пройдёт на базе без ошибок.
База 1С, которую последовательно переносили с версии на версию SQL Server, — как раз такой случай: пока один безошибочный прогон WITH DATA_PURITY не сделан, эта категория проверок молчит. И ещё одно: ошибки, найденные с DATA_PURITY, ключами восстановления DBCC не исправляются.
Куда смотреть результат проверки
SQL Server пишет итог проверки в свой журнал ошибок, а не только в окно клиента. Если команда отработала успешно, сообщение в журнале говорит об успехе и о том, сколько времени она шла.
Отдельно SQL Server запоминает дату и время последней проверки, которая прошла без ошибок. Называется эта дата last known clean check; устоявшегося русского перевода у термина нет, и я оставляю его латиницей. При запуске базы SQL Server пишет её в журнал ошибок и в EventLog (EventID-17573) такой строкой: CHECKDB for database '<database>' finished without errors on 2022-05-05 18:08:22.803 (local time). This is an informational message only; no user action is required. Ищите эту строку там, где в журнале записан запуск базы. Практический смысл у неё простой: по ней видно, когда база в последний раз проходила проверку чисто.
Если CHECKDB наткнулся на повреждение, SQL Server создаёт дамп стека: файлы SQLDump<nnnn>.txt, .log и .mdmp в каталоге LOG службы SQL Server. Доступ к ним есть у учётной записи службы и у членов роли sysadmin.
Когда проверка прерывается, в сообщении приходит код состояния от 0 до 5. Запомнить стоит два. Состояние 3 значит, что команду DBCC прервало повреждение в метаданных. Состояние 4 — что обнаружен assert или нарушение доступа (access violation).
Три ключа REPAIR_*: что делает каждый
Ключей восстановления у CHECKDB три, и один из них не чинит ничего.
| Ключ | Что делает | Формулировка Microsoft (en-us) |
|---|---|---|
REPAIR_FAST | Действий по восстановлению не выполняет. Синтаксис оставлен только ради обратной совместимости | «Maintains syntax for backward compatibility only. No repair actions are performed» |
REPAIR_REBUILD | Выполняет исправления, при которых потеря данных исключена. Среди них могут быть быстрые, например восстановление отсутствующих строк в некластеризованных индексах, и более долгие, например перестроение индекса | «Performs repairs that have no possibility of data loss. This option might include quick repairs, such as repairing missing rows in nonclustered indexes, and more time-consuming repairs, such as rebuilding an index» |
REPAIR_ALLOW_DATA_LOSS | Пытается устранить все обнаруженные ошибки. Эти исправления могут привести к частичной потере данных | «Tries to repair all reported errors. These repairs can cause some data loss» |
У REPAIR_REBUILD есть граница: ошибки, связанные с данными FILESTREAM, он не исправляет.
Правило у всех трёх ключей общее. Применять их можно только как крайнее средство, а базу перед этим нужно перевести в однопользовательский режим. Это требование платформы к любому ключу REPAIR_*, а не особенность какого-то одного.
Почему Microsoft ставит восстановление из копии впереди REPAIR_ALLOW_DATA_LOSS
Ошибки, о которых сообщил DBCC CHECKDB, лечат в первую очередь восстановлением из последней известной хорошей резервной копии. С REPAIR_ALLOW_DATA_LOSS можно потерять больше данных, чем при восстановлении из такой копии. Заменой копии этот ключ не служит. В своём предупреждении о потере данных Microsoft называет его так: «emergency last resort option recommended for use only if restoring from a backup isn't possible» — аварийное крайнее средство, которое рекомендовано, только когда восстановиться из копии невозможно.
Теперь о том, откуда берётся потеря. Часть ошибок исправляется только ключом REPAIR_ALLOW_DATA_LOSS, и исправление может состоять в деаллокации строки, страницы или серии страниц. Деаллоцированные данные пользователю больше не доступны и восстановлению не подлежат. Поэтому перед таким восстановлением обязательно сделайте физические копии файлов базы — .mdf, .ndf, .ldf, файлы полнотекстовых каталогов.
Ограничений и связей между таблицами операция восстановления не учитывает. Отсюда обязательный шаг после REPAIR_ALLOW_DATA_LOSS: проверить ссылочную целостность базы командой DBCC CHECKCONSTRAINTS.
Любой запуск с ключом REPAIR_* оборачивайте в транзакцию. Выполните BEGIN TRANSACTION перед командой и посмотрите на результат. Устраивает — COMMIT TRANSACTION. Не устраивает — ROLLBACK TRANSACTION отменит то, что сделало восстановление. Для базы учёта это дешёвая страховка, и я считаю её обязательной.
Порядок проверки базы 1С по шагам
- Сделать резервную копию. Перед запуском с
REPAIR_ALLOW_DATA_LOSSэто рекомендация, а физические копии файлов базы перед самим восстановлением — уже требование. Мы в своём инциденте делали бэкап раньше — до первого прогона проверки. - Запустить проверку:
DBCC CHECKDB(N'имя_базы') WITH NO_INFOMSGS. - Прочитать результат — в выводе Management Studio и в журнале ошибок SQL Server, куда по завершении команды пишется сообщение.
- Если найдены ошибки — восстанавливать базу из последней известной хорошей резервной копии. Это основной путь.
- Ключи
REPAIR_*— только если восстановление из копии невозможно. Перед этим база переводится в однопользовательский режим; в нашем инциденте это делалось запросомALTER DATABASE KA SET SINGLE_USER WITH ROLLBACK IMMEDIATE. - Запускать восстановление внутри транзакции, чтобы результат можно было откатить.
- После
REPAIR_ALLOW_DATA_LOSSпроверить ссылочную целостность командойDBCC CHECKCONSTRAINTS. - Вернуть базу в многопользовательский режим — в нашем случае запросом
ALTER DATABASE KA SET MULTI_USER. Так база выходит из однопользовательского режима, включённого ради ключейREPAIR_*.
2603 ошибки согласованности: как это было у нас
Дальше — наш собственный случай, из-за которого эта страница вообще появилась. Мы описали его здесь в декабре 2019 года, и цифры с тех пор не менялись. Ценность его в одном: рекомендованный путь в нём до конца не сработал.
Началось всё с жалобы бухгалтера: перестали проводиться документы, 1С сообщила о проблемах с согласованностью внутри базы и предложила проверку на согласованность. Мы сделали бэкап текущего состояния, перевели базу в однопользовательский режим и запустили DBCC CHECKDB(N'ka') WITH NO_INFOMSGS. Проверка шла около 15 минут.
Ответ сервера: «CHECKDB обнаружил 0 ошибок размещения и 2603 ошибок согласованности в базе данных „KA“». Разбивка по объектам оказалась неровной: 1783 ошибки в таблице _AccRg1051, 766 не связанных ни с одним объектом, 49 в _AccRg1025, 3 в _AccRgAT21046 и по одной в sys.sysdbfiles и sys.sysxmlcomponent.
Бэкапы показали, что ошибка накапливалась
Сначала мы пошли по рекомендованному пути и начали восстанавливать копии. Выяснилось, что ошибка накапливалась: чем раньше сделан бэкап, тем меньше в базе ошибок, и так до самого дальнего, 14-дневного. Примерно на третьем бэкапе число ошибок перестало уменьшаться. Стало ясно, что этим путём мы потеряем актуальность базы, а проблему не решим.
Вот здесь инструкция и упирается в живую аварию. Восстановление из последней известной хорошей копии — основной путь, и мы начали именно с него. Только «последней хорошей» копии у нас не оказалось: повреждение уже жило в базе к моменту самого дальнего доступного бэкапа.
REPAIR_REBUILD и REPAIR_ALLOW_DATA_LOSS
REPAIR_REBUILD выполнился без эффекта: те же 2603 ошибки. Мы вернули базу в многопользовательский режим, провели обслуживание, перепроверили — результат тот же. Тестирование и исправление средствами 1С завершилось ошибкой, выгрузка в *.dt не удалась.
Затем пошёл REPAIR_ALLOW_DATA_LOSS. После нескольких прогонов количество ошибок немного уменьшилось: 2603 стало 2518. И остановилось. База по-прежнему не выгружалась и не лечилась средствами 1С, а дальнейшие чередования REPAIR_REBUILD и REPAIR_ALLOW_DATA_LOSS не давали ничего.
Задним числом всё сходится. REPAIR_ALLOW_DATA_LOSS пытается устранить найденные ошибки — именно пытается. У нас попытка закончилась на 85 ошибках из 2603.
Что сработало — и почему это не рекомендация
Сработала очистка проблемной таблицы регистра без удаления самой таблицы: TRUNCATE TABLE _AccRg1051. Повторный DBCC CHECKDB через 15 минут показал, что все ошибки исчезли, в том числе и в остальных таблицах. База выгрузилась в *.dt, загрузилась обратно, проблемные документы у бухгалтера заработали.
Проговорю прямо, потому что этот абзац легче всего прочитать как инструкцию. TRUNCATE TABLE на таблице регистра — операция с потерей данных. Мы применили её тогда, когда рекомендованные пути были пройдены и не дали результата, и я привожу её как факт о том, что было сделано в конкретном инциденте, а не как совет для вашей базы. Что именно потерял клиент и как это закрывали в учёте, у нас не записано — цена этого шага неизвестна. TRUNCATE TABLE — отдельная команда, а не ключ CHECKDB, и помогла она в одном нашем случае.
Через час ошибка вернулась
Самое полезное в этой истории случилось после того, как всё заработало. Через час ошибка повторилась. Вывод 2019 года я не меняю: выгрузка в *.dt — не панацея. Вылечило базу тестирование и исправление в режиме конфигуратора 1С.
Тестирование с исправлением в конфигураторе 1С — операция необратимая. Поэтому 1С советует перед ним сделать резервную выгрузку информационной базы. В «1С:Бухгалтерии 8» редакции 3.0 порядок такой: запустить базу от пользователя с ролью «Администратор системы» в режиме «Конфигуратор», открыть раздел «Администрирование – Тестирование и исправление», установить флажки нужного режима проверки и нажать «Выполнить».
В рекомендацию о резервной выгрузке наш случай попадает неудобной стороной. На тяжёлой стадии базу не удалось выгрузить в *.dt вовсе, да и само тестирование завершилось ошибкой. Страховкой у нас в тот момент служила резервная копия средствами SQL Server, сделанная до первого прогона проверки. А вылечил базу в итоге тот самый необратимый прогон — в самом конце истории, когда починенная база сломалась снова.
Есть базы 1С, где проверку ссылочной целостности включать не надо. В информационных базах, хранящих неполный набор объектов, такую проверку, а тем более проверку с исправлением, проводить не следует (методическая поддержка 1С:ИТС, доступ по подписке). Это базы обмена: часть ссылок в них разрешается только в «глобальной» базе. Проверка в таких условиях выдаст сообщения об ошибках, а тестирование с исправлением может привести к частичному разрушению уже в «глобальной» базе — к изменению содержания или полному удалению объектов ссылки.
Управляет проверкой флажок в диалоге «Тестирование и исправление», а из командной строки — параметры ключа /IBCheckAndRepair: -LogIntegrity включает проверку только логической целостности, -LogAndRefsIntegrity — логической и ссылочной. Правило о базах обмена записано в 2008 году, и версия платформы в нём не названа. Проверить, не про вашу ли базу это правило, стоит до того, как ставить флажок.
Актуально ли это для вашей версии SQL Server
У трёх ключей REPAIR_* и у требования однопользовательского режима версионных оговорок нет: правила одни для SQL Server начиная с 2017, Azure SQL Database и Azure SQL Managed Instance. Это и есть ответ на вопрос, не устарела ли процедурная часть текста семилетней давности.
От версии зависят другие параметры. MAXDOP применим начиная с SQL Server 2014 (12.x) Service Pack 2. EXTENDED_LOGICAL_CHECKS работает при уровне совместимости 100, появившемся в SQL Server 2008. До SQL Server 2005 SP2 запуск CHECKDB очищал кэш планов, начиная с SP2 не очищает. В SQL Server 2016 и новее часть дополнительных проверок (вычисляемые столбцы, столбцы UDT, отфильтрованные индексы) по умолчанию не выполняется, что экономит время. А в Azure SQL Database Hyperscale DBCC CHECKDB не поддерживается вовсе — вместо него используется DBCC CHECKTABLE ('TableName') WITH TABLOCK.
Цифры нашего инцидента 2019 года идут без привязки к версии: это один случай на одной базе.
Что с этим делать в регламенте
В плане обслуживания базы 1С проверка целостности стоит первой задачей, перед всеми остальными регламентными операциями. Как собирается сам план в Microsoft SQL Server Management Studio, расписано в статье «Обслуживание баз Microsoft SQL Server для работы 1С»; здесь я эту тему не повторяю.
Барьер, который я считаю честным назвать: запускать REPAIR_ALLOW_DATA_LOSS на продуктивной базе учёта в одиночку — плохая идея. Деаллоцированные данные назад не вернуть. Если в компании нет администратора СУБД, работу с базой 1С разумнее закрывать регламентом, а не героизмом в момент аварии. В услуге «Сопровождение 1С» компании «+Альянс» на это отведены два шага из пяти. На аудите базы мы смотрим конфигурацию, доработки, регламентные задания и состояние копий. На шаге резервного копирования настраиваем копии базы и проверяем восстановление. После этой статьи второй из них читается иначе: при ошибках CHECKDB восстановление из хорошей копии — основной путь.
Частые вопросы
Как запустить DBCC CHECKDB?
Запрос выполняется в любом клиенте T-SQL, например в Management Studio, под учётной записью с членством в роли sysadmin или db_owner. Минимальная форма для базы 1С: DBCC CHECKDB(N'имя_базы') WITH NO_INFOMSGS. Ключ NO_INFOMSGS подавляет информационные сообщения, поэтому на чистой базе в выводе останется только The command(s) completed successfully. Для регулярных запусков на работающей системе подходит PHYSICAL_ONLY, но полную проверку всё равно надо делать периодически.
Нужен ли однопользовательский режим для обычной проверки?
Однопользовательский режим требуется для ключей восстановления: без него ни один из трёх ключей REPAIR_* применить нельзя. Обычная проверка работает через внутренний снимок базы, и этот снимок предотвращает блокировки и конфликты параллельной работы. Блокировки CHECKDB берёт в двух случаях: если снимок создать нельзя или если указан TABLOCK. Тогда для проверок размещения нужна исключительная блокировка базы, а для проверок таблиц — общие блокировки таблиц.
Сколько времени идёт проверка базы 1С?
В нашем инциденте DBCC CHECKDB(N'ka') WITH NO_INFOMSGS на базе того клиента отработал около 15 минут, а результат повторной проверки после очистки таблицы мы увидели через те же 15 минут. Замер один, и размер той базы у нас не записан, поэтому на свою базу эти 15 минут не переносите — замерьте первый прогон у себя. Для частых запусков на большой базе есть PHYSICAL_ONLY: с ним проверка может пройти намного быстрее.
Чем REPAIR_REBUILD отличается от REPAIR_ALLOW_DATA_LOSS?
REPAIR_REBUILD выполняет только те исправления, при которых данные не теряются. Примеры — вернуть отсутствующие строки в некластеризованный индекс или перестроить индекс. REPAIR_ALLOW_DATA_LOSS пытается исправить всё, что нашла проверка, и платой может стать часть данных — вплоть до деаллокации строки, страницы или серии страниц, после которой эти данные недоступны и не восстанавливаются. После REPAIR_ALLOW_DATA_LOSS нужно проверить ссылочную целостность командой DBCC CHECKCONSTRAINTS.
CHECKDB нашёл ошибки согласованности. С чего начинать?
С резервной копии. Первым делом базу восстанавливают из последней известной хорошей копии: это основной способ уйти от ошибок, о которых сообщил DBCC CHECKDB. К ключу REPAIR_ALLOW_DATA_LOSS переходят, только если восстановить базу из копии нельзя. В нашем инциденте этот путь не помог по конкретной причине: ошибка накапливалась и присутствовала уже в самом дальнем доступном бэкапе за 14 дней.
Поможет ли встроенное «Тестирование и исправление» 1С?
В нашем инциденте на тяжёлой стадии оно не помогло: прогон средствами 1С оборвался ошибкой, и выгрузить базу в *.dt тоже не получилось. А на финальной стадии, после того как ошибка вернулась через час, базу вылечило именно тестирование и исправление в режиме конфигуратора. Это два факта об одном случае, а не правило. Перед запуском сделайте резервную выгрузку информационной базы: процедура тестирования с исправлением необратима (страница 1С:ИТС, доступ по подписке).
Где посмотреть, когда база в последний раз проверялась без ошибок?
В журнале ошибок SQL Server. Дату последней проверки без ошибок сервер пишет туда при запуске базы: CHECKDB for database '<database>' finished without errors on <дата и время> (local time). This is an informational message only; no user action is required. Та же дата при запуске базы попадает в EventLog, EventID-17573. По-английски это last known clean check; устоявшегося перевода на русский у термина нет.
Александр Жогов, основатель компании «+Альянс».
