База 1С не открывается после обновления конфигурации: порядок действий, когда копии нет
Иван Недомолков · Опубликовано:
Обновление конфигурации падает через несколько секунд после старта, и при следующем входе конфигуратор спрашивает: “При обновлении данных, после последней реструктуризации, произошла критическая ошибка. Повторить обновление?”. Пользователи в базу больше не входят. Если копия до обновления есть, задача решается восстановлением. Эта статья про случай, когда её нет.
Порядок ниже проверен на рабочей базе: платформа 8.3.17, клиент-серверный вариант, MS SQL Server 2019 на том же сервере, “Розница для Казахстана” 2.2 с доработками, около 3,5 ГБ данных и десяти пользователей. От сбоя до работающих пользователей прошло 57 минут, данные не потеряли. Выгрузка и загрузка заняли шесть минут, всё остальное время ушло на шаги, которые не помогли, и они тоже разобраны. История от первого лица, с ошибками нашего ИИ-агента на сервере, опубликована на Инфостарте.
Шаг 1. Снять копию сломанной базы
Звучит странно, но это первое действие. Откатить обновление такая копия не позволит. Зато любой следующий шаг станет обратимым, а их будет несколько, и не все удачные. На 3,5 ГБ полная копия заняла 23 секунды.
-- Копия текущего, уже сломанного состояния. COPY_ONLY не ломает цепочку обычных копий.
BACKUP DATABASE [YourDb]
TO DISK = N'D:\Backup\YourDb_broken.bak'
WITH COPY_ONLY, COMPRESSION, CHECKSUM, STATS = 10;
Шаг 2. Найти этап, на котором упало
Обновление конфигурации базы данных идёт этапами, и от этапа зависит, что делать дальше. Ответ лежит в журнале регистрации: он читается и тогда, когда сама база не открывается, файлы журнала лежат в каталоге базы на сервере 1С. Нужны три события по порядку времени.
07:13:03 DBConfigUpdateStart начало обновления конфигурации БД
07:13:09 PredefinedDataUpdate "Выполняется обновление предопределенных данных"
07:13:18 DBConfigUpdateError текста ошибки нет
| Что видно в журнале | Что это значит | Куда идти |
|---|---|---|
| ошибка до любых событий реструктуризации | структура не менялась | один чистый повтор обновления, шаг 3 |
| реструктуризация прошла, упало на предопределённых данных или позже | структура уже новая, база помечена как незавершённая | не тратить время на починку изнутри, шаг 4 |
DBConfigUpdateError с текстом | платформа назвала причину | лечить причину, потом повтор |
У нас было ровно второе: реструктуризация прошла, упал следующий этап, и текста ошибки платформа не записала.
Шаг 3. Один чистый повтор, без помех
Повтор имеет смысл, но только один и только в чистых условиях. Иначе его оборвёт что-то постороннее, и вы так и не узнаете, помог бы он или нет. У нас первый “Да” на вопрос о повторе оборвал наш же перезапуск агента сервера, второй - тонкий клиент пользователя, который сам переподключился к базе.
Чистые условия выглядят так: в консоли кластера установить блокировку начала сеансов с кодом разрешения и войти в конфигуратор с этим кодом.
"C:\Program Files\1cv8\8.3.17.1549\bin\1cv8.exe" DESIGNER /S Server1C\Base01 ^
/N <пользователь> /P <пароль> /UC <код разрешения> ^
/UpdateDBCfg /Out D:\Logs\update.log
Если в логе одна строка Infobase structure error, а интерактивный повтор возвращает тот же вопрос, дальше повторять бессмысленно.
Чего не делать
Каждый пункт ниже мы попробовали, и каждый стоил времени.
| Действие | Почему не помогает |
|---|---|
| перезапуск агента сервера 1С | состояние сбоя записано в самой базе, а не в кэше сервера. При открытом конфигураторе ещё и добавляет ошибку “не назначен сеанс”, у нас это 15 минут путаницы |
| перезагрузка сервера целиком | то же: признак незавершённого обновления хранится в базе, перезагрузка его не трогает |
| запрет регламентных заданий в консоли кластера | не ставится: “Обнаружена незавершенная операция сохранения конфигурации”. Флаг хранится в базе, а база не открывается. Блокировка начала сеансов при этом ставится, она хранится в кластере |
| снятие лимитов памяти кластера, перезапуск SQL Server | советы из интернета под другую болезнь. Сначала проверьте факт: были ли лимиты, есть ли зависшие сеансы 1С на SQL Server. У нас лимиты были нулевые, зависших сеансов не было |
ibcmd infobase config apply | отвечает [FATAL] Обнаружена незавершенная операция сохранения конфигурации. Штатного способа снять этот признак на сломанной базе у платформы нет |
Править служебные таблицы руками, чтобы снять признак незавершённой операции, мы не советуем. Это лечение вслепую на базе без копии.
Шаг 4. Путь вперёд: .dt из базы, которая не открывается
Утилита ibcmd из поставки платформы работает с базой на уровне СУБД, без кластера и без сеансов. Поэтому она выгружает .dt там, где конфигуратор и клиент в базу не пускают. В 8.3.17 у неё нет параметра пользователя 1С, в командах только логин SQL. Имена сервера и баз ниже условные.
:: 1. Выгрузка из неоткрывающейся базы (у нас 105 секунд, файл 438 МБ)
ibcmd infobase dump --dbms=MSSQLServer --db-server=Server1C --db-name=DB01 ^
--db-user=<sql_user> --db-pwd=<sql_pwd> D:\Backup\DB01.dt
:: 2. Новая база на SQL Server из этой выгрузки (у нас 274 секунды).
:: date-offset такой же, как у исходной базы
ibcmd infobase create --dbms=MSSQLServer --db-server=Server1C --db-name=DB01_new ^
--db-user=<sql_user> --db-pwd=<sql_pwd> --locale=ru_RU --date-offset=2000 ^
--create-database --restore=D:\Backup\DB01.dt
date-offset должен совпасть с исходной базой, иначе даты в новой базе съедут. Смещение задаётся при создании базы, у нас стояло 2000, как обычно у баз на MS SQL.
Почему новая база открылась, а старая нет, до конца мы не знаем. В .dt уходят конфигурация и данные, новая база собирается из них с нуля, и состояния незавершённого обновления в ней нет. Этого хватило.
Шаг 5. Проверка под тестовым именем и подмена
Новую базу сначала регистрируют в кластере под другим именем и сразу запрещают в ней регламентные задания. Иначе обмены и прочие задания пойдут из двух баз одновременно, у нас это был обмен с маркетплейсом.
:: Тестовая регистрация, база СУБД уже есть, поэтому без --create-database
rac infobase create --cluster=<id> --name=Base01_new --dbms=MSSQLServer --db-server=Server1C ^
--db-name=DB01_new --locale=ru --db-user=<sql_user> --db-pwd=<sql_pwd> ^
--license-distribution=allow localhost:1545
rac infobase update --cluster=<id> --infobase=<id_new> --scheduled-jobs-deny=on localhost:1545
Проверка в два слоя: пакетный конфигуратор с /UpdateDBCfg должен вернуть код 0, и человек должен открыть базу в режиме Предприятия и посмотреть данные глазами.
Переключение делается так, чтобы у пользователей не менялось ничего: их строка подключения как смотрела на старое имя, так и смотрит, а под этим именем в кластере оказывается новая база СУБД.
:: Убрать тестовую регистрацию. Сама база на SQL Server остаётся
rac infobase drop --cluster=<id> --infobase=<id_new> localhost:1545
:: Старому имени дать новую базу СУБД
rac infobase update --cluster=<id> --infobase=<id_Base01> --db-name=DB01_new localhost:1545
:: Остановить RAS и агент сервера, удалить srvinfo\reg_1541\snccntx*, запустить агент, затем RAS
:: Снять блокировки
rac infobase update --cluster=<id> --infobase=<id_Base01> ^
--scheduled-jobs-deny=off --sessions-deny=off --permission-code="" localhost:1545
Старую базу на SQL Server не удаляйте, пока новая не проработает неделю. У нас она так и осталась страховкой.
Данные мы не потеряли: выгрузка взяла всё, что было в базе на момент сбоя, а после начала обновления никто ничего не вводил. Последняя ручная копия была почти месячной, и восстановление из неё отняло бы весь этот месяц.
После: копия делается регламентом, а не памятью
Главная ошибка той истории не в выборе шагов, а в том, что копии до обновления не было. Накануне при разборе тормозов уже было видно, что последняя копия ручная и ей почти месяц, база в полной модели восстановления без копий журнала, журнал транзакций дорос до 48 ГБ, заданий обслуживания нет. Скрипты подготовили и отложили. Отчёт о дыре сам по себе ничего не решает, решает правило: без свежей копии обновление не запускаем.
В тот же день завели задания SQL Server Agent: полная копия каждый день в 23:00, копия журнала каждый час, статистика, индексы, проверка целостности, хранение 14 дней на отдельном диске. Основа заданий такая:
-- Полная копия, задание раз в сутки
BACKUP DATABASE [YourDb]
TO DISK = N'E:\Backup\YourDb_full.bak'
WITH INIT, COMPRESSION, CHECKSUM;
-- Копия журнала, задание раз в час. Без неё полная модель восстановления
-- только растит журнал транзакций и не даёт откатиться на минуту
BACKUP LOG [YourDb]
TO DISK = N'E:\Backup\YourDb_log.trn'
WITH NOINIT, COMPRESSION, CHECKSUM;
В реальном задании имя файла лучше собирать с датой и временем и чистить старше 14 дней, но смысл в этих двух командах. С ними та же авария закрывается восстановлением на минуту до запуска обновления.
Проверить перед обновлением, сколько часов назад была последняя полная копия и есть ли копии журнала, можно одним запросом:
-- Последняя полная копия и последняя копия журнала по каждой базе
SELECT d.name,
d.recovery_model_desc,
MAX(CASE WHEN b.type = 'D' THEN b.backup_finish_date END) AS полная,
MAX(CASE WHEN b.type = 'L' THEN b.backup_finish_date END) AS журнал
FROM sys.databases AS d
LEFT JOIN msdb.dbo.backupset AS b ON b.database_name = d.name
WHERE d.database_id > 4
GROUP BY d.name, d.recovery_model_desc
ORDER BY d.name;
Если в колонке “полная” пусто или дата старше суток, а у базы с моделью FULL пусто в колонке “журнал”, обновление ждёт. Те же две дыры с вердиктом “чинить” показывает Чек-ап СУБД под 1С, а развернуть копию рядом для репетиции обновления помогают скрипты восстановления из бэкапа SQL.
Если не хочется держать это в голове, сопровождение баз 1С у нас начинается именно с заданий копирования и проверки, что из копии база действительно поднимается.