Каждый разработчик и администратор баз данных 1С рано или поздно сталкивается с дилеммой: нужно срочно исправить критическую ошибку в коде общего модуля, но в системе работают пользователи. Выгонять всех вручную — долго и болезненно для бизнес-процессов. На помощь приходит механизм, который в сообществе 1С ласково и одновременно с ужасом называют «демоническим обновлением» — динамическое обновление конфигурации.
В этой статье мы подробно разберем, как устроен этот механизм изнутри на уровне СУБД, какие скрытые угрозы он в себе таит, почему системные администраторы готовы «казнить» за его использование и как спасти базу данных, если динамическое обновление все-таки привело к критическому сбою.
Прежде чем анализировать проблемы, давайте вспомним основы архитектуры платформы 1С:Предприятие 8. В любой информационной базе одновременно существуют три конфигурации (не считая конфигурации хранилища):
Обычное монопольное обновление полностью замещает конфигурацию БД новой сохраненной конфигурацией, требуя монопольного доступа и нередко выполняя реструктуризацию таблиц. Динамическое обновление пытается обойти это ограничение, заменяя исполняемый код «на лету» без отключения пользователей.
Давайте заглянем под капот СУБД (MS SQL Server, PostgreSQL или др.) и посмотрим, что происходит в таблицах базы данных при запуске динамического обновления. Вся конфигурация хранится в виде бинарных файлов в служебных таблицах:
dbo.Config — основная таблица конфигурации базы данных.dbo.ConfigSave — таблица, где хранятся промежуточные изменения разработчика до их принятия.Когда мы запускаем динамическое обновление, платформа не просто перезаписывает таблицу Config. Этот процесс выполняется пошагово:
Config под временными уникальными идентификаторами.Config создаются специальные записи-маркеры в поле FileName со значениями commit, dynamicCommit и dbStruFinal. Эти записи служат индикатором того, что транзакция динамического обновления находится в процессе выполнения.Представим ситуацию: в момент записи служебных маркеров в СУБД происходит непредвиденный сбой. Это может быть кратковременный разрыв сетевого соединения между сервером 1С и СУБД, аварийное завершение рабочего процесса rphost, отключение питания сервера или случайное закрытие Конфигуратора разработчиком.
В этот момент база данных переходит в **несогласованное (битое) состояние**. Транзакция не завершена, а в таблице Config зависают незавершенные маркеры. При следующей попытке запустить Конфигуратор или войти в режим «1С:Предприятие» пользователи и разработчики упрутся в бесконечный цикл критических ошибок:
«Внимание!!! При обновлении данных, после последней реструктуризации, произошла критическая ошибка. Повторить обновление?»
При нажатии кнопки «Да» система выдает следующее системное сообщение и аварийно завершает работу:
«Обнаружена незавершенная операция сохранения конфигурации. Для продолжения работы необходимо завершить операцию».
Если вы попали в такую ситуацию, стандартная утилита тестирования и исправления файловых баз chdbfl.exe или штатные средства Конфигуратора не помогут, так как они просто не запустятся. Единственный выход (помимо отката к ночному бэкапу, что означает потерю дневных данных пользователей) — прямое вмешательство в СУБД.
Рассмотрим пошаговый алгоритм лечения базы данных с помощью SQL-запроса. Нам необходимо принудительно удалить «зависшие» маркеры незавершенной транзакции:
-- Шаг 1: Удаляем записи-маркеры незавершенного динамического обновления
DELETE FROM Config WHERE FileName = 'commit'
DELETE FROM Config WHERE FileName = 'dbStruFinal'
DELETE FROM Config WHERE FileName = 'dynamicCommit'
-- Шаг 2: Очищаем таблицу временных сохранений конфигурации
DELETE FROM ConfigSave
После выполнения данного запроса на сервере СУБД заблокированные процессы освобождаются, и Конфигуратор успешно запустится в обычном режиме. Вы сможете выполнить полноценное монопольное обновление конфигурации базы данных.
В более тяжелых случаях, когда таблица Config повреждена сильнее и простым удалением маркеров обойтись не удается, применяется метод «базы-донора». Разберем этот метод по шагам:
Config в нашей рабочей базе и копируем в нее данные из чистой базы-донора.
-- Очищаем разрушенную таблицу конфигурации в рабочей базе
DELETE FROM [РабочаяБаза].[dbo].[Config]
-- Переносим структуру и данные чистой конфигурации из донора
INSERT INTO [РабочаяБаза].[dbo].[Config]
SELECT * FROM [БазаДонор].[dbo].[Config]
Этот радикальный метод позволяет восстановить работоспособность конфигурации без потери пользовательских данных, хранящихся в других таблицах СУБД.
Помимо очевидной угрозы падения базы при обрыве транзакции, существует ряд скрытых проблем, которые могут проявиться через дни или даже недели после динамического обновления.
Один из самых коварных багов платформы 1С заключается в следующем: если выполнять динамическое обновление многократно подряд (например, 5-10 раз), а затем запустить стандартное обновление с изменением метаданных (требующее реструктуризации таблиц), система может «забыть» часть промежуточного кода. Происходит неожиданный откат конфигурации БД к состоянию, которое предшествовало первому динамическому обновлению в цепочке. Разработчики внезапно обнаруживают, что их давно отлаженный код общего модуля просто исчез.
При использовании PostgreSQL в связке с 1С динамическое обновление очень часто вызывает ошибку следующего вида: ERROR: relation "_referenceXXXX" does not exist. Это обусловлено тем, что PostgreSQL кэширует планы выполнения запросов. Когда структура метаданных обновляется динамически, старые сеансы пользователей продолжают использовать старые закэшированные планы СУБД, обращаясь к несуществующим внутренним таблицам или индексам. Итог — аварийное завершение работы процессов СУБД.
Почему системные администраторы жалуются на то, что динамическое обновление «мучает» сервер приложений? Ответ кроется в анализе Технологического журнала (ТЖ) 1С. После динамического наката изменений рабочие процессы сервера вынуждены одновременно поддерживать в оперативной памяти несколько разных версий метаданных конфигурации — одну для пользователей, которые перезапустили систему, и другие версии для тех, кто остался в старых сеансах.
Это приводит к следующим последствиям:
Попытка подключения к контексту сервера с неподходящей версией метаданных.rphost.При динамическом обновлении часто ломается отладка кода. Кэш Конфигуратора разработчика рассинхронизируется с кэшем на сервере приложений. В результате точки останова в коде перестают срабатывать, либо отладчик начинает «прыгать» по пустым строкам, так как реальные номера строк кода в файле на сервере не совпадают с отображаемыми в Конфигураторе.
Если после динамического обновления пользователи жалуются на странное поведение программы (например, формы открываются некорректно, не видны новые кнопки или выдаются ошибки обращения к методам), это верный признак рассинхронизации кэша. Он хранится в трех независимых местах:
%localappdata%\1C\1cv8\... и %appdata%\1C\1cv8\... (каталоги Config, DBNameCache, SICache). Его очистка решает проблемы конкретного клиента.C:\Program Files\1cv8\srvinfo\reg_1541\...). При сбоях здесь помогает только перезапуск службы 1С:Предприятие.Что же делать, если обновиться нужно срочно, но рисковать работоспособностью сервера нельзя? Рассмотрим лучшие практики, рекомендуемые экспертами по технологическим вопросам:
Мы можем встроить в конфигурацию механизм автоматического отключения или предупреждения пользователей, если система была обновлена динамически. Для этого используется программный метод КонфигурацияБазыДанныхОбновленаДинамически(). Например, разместим в обработчике ожидания или при начале работы системы следующий код:
Если КонфигурацияБазыДанныхОбновленаДинамически() Тогда
ПоказатьПредупреждение(, "Конфигурация базы данных была обновлена разработчиком.
|Для корректной работы программы, пожалуйста, перезапустите сеанс!");
КонецЕсли;
После успешного завершения динамического обновления Конфигуратор выдает диалоговое окно: «Конфигурация базы данных успешно обновлена. Перезапустить Конфигуратор?». Всегда нажимайте «Нет»! Закрывайте Конфигуратор вручную и запускайте его заново. Это гарантирует очистку локального кэша метаданных разработчика и предотвращает рассинхронизацию при последующих доработках кода.
Для оперативного исправления ошибок в коде общего модуля или формы используйте механизм Расширений конфигурации. Вместо динамического обновления основной конфигурации вы можете оперативно создать небольшое расширение, переопределить метод с аннотацией &Вместо, &Перед или &После и применить его. Платформа работает с расширениями по совершенно иным механизмам взаимодействия СУБД и кэша, что практически исключает риски падения сервера или разрушения основной таблицы Config.
Программные проблемы лучше всего предотвращаются административными регламентами. Настройте автоматическое завершение спящих и неактивных сеансов пользователей в ночное время через консоль администрирования серверов 1С или регламентные задания СУБД. Это позволит вам выполнять полноценные, безопасные и монопольные обновления конфигурации без риска нарушить бесперебойную работу предприятия.