Каждый разработчик 1С рано или поздно сталкивается с так называемым «демоническим» (динамическим) обновлением базы данных. Этот механизм невероятно удобен на практике: он позволяет быстро внедрять мелкие исправления в модули без необходимости выгонять сотни пользователей из системы. Однако при совместной работе через Хранилище конфигурации динамическое обновление может сыграть злую шутку. В один «прекрасный» день вы обнаружите, что ваши изменения, успешно внесенные и протестированные пару недель назад, бесследно исчезли из Хранилища, а сама платформа рассинхронизировалась до такой степени, что сравнение конфигураций считает абсолютно разный код идентичным.
В этой статье мы подробно разберем, почему возникает этот опаснейший сбой, проанализируем внутренние механизмы кэширования платформы 1С и СУБД, а также изучим пошаговый алгоритм восстановления стабильной работы Хранилища и базы данных.
Рассмотрим типичный сценарий, с которым столкнулся автор темы. В рабочей базе захватывается общий модуль (например, модуль регламентных заданий ОбщийМодуль.РегламентныеЗаданияСервер), в него вносятся изменения, после чего выполняется динамическое обновление рабочей базы. Код помещается в Хранилище конфигурации. Всё работает исправно.
Через некоторое время другой разработчик в тестовой базе, подключенной к этому же Хранилищу, захватывает тот же самый общий модуль, вносит свои изменения и помещает их обратно. В этот момент происходит катастрофа: изменения первого разработчика полностью затираются. Выясняется, что при захвате объекта платформа посчитала локальную версию модуля актуальной и не стала скачивать последнюю версию из Хранилища. В результате разработчик получил устаревший код, наложил на него свои правки и отправил эту «смесь» обратно в Хранилище, уничтожив результаты чужого труда.
Ситуация усугубляется еще более странным поведением системы: при выгрузке файла конфигурации (.cf) из рабочей базы и его загрузке в тестовую базу изменения физически отсутствуют в интерфейсе Конфигуратора, однако если открыть этот же файл через меню «Файл — Открыть», код на месте! Более того, операция сравнения и объединения конфигураций утверждает, что основная конфигурация и конфигурация базы данных абсолютно идентичны.
Описанная ситуация является классическим проявлением известного бага платформы 1С (особенно ярко выраженного в версиях линейки 8.3.10, включая релиз 8.3.10.2580). Суть ошибки заключается в следующем:
Если после выполнения динамического обновления базы данных разработчик не перезапускает Конфигуратор, а продолжает вести в нем разработку и работать с Хранилищем, кэш метаданных сеанса Конфигуратора не обновляется. При попытке захватить объект система обращается к своей локальной памяти. Из-за несоответствия хэш-сумм Конфигуратор ошибочно считает, что версия в СУБД и версия в Хранилище совпадают с его текущим состоянием. Захват происходит без принудительного получения актуального текста модуля. При последующем помещении («коммите») старый код перезаписывает новый.
При выполнении динамического обновления платформа 1С не заменяет метаданные «на лету» в таблице конфигурации. Вместо этого в СУБД (например, MS SQL Server) в системной таблице Config создаются временные записи-маркеры. Давайте проанализируем эти маркеры:
dynamicCommit — указывает на наличие незавершенных транзакций динамического перестроения метаданных.dbStruFinal — фиксирует финальную структуру базы данных.DynamicallyUpdated — флаг, сообщающий серверу приложений, что база была обновлена динамически.Если в процессе динамического обновления произошел сетевой сбой, или если Конфигуратор был аварийно завершен, эти маркеры остаются «зависшими» в СУБД. В результате сервер приложений 1С (процессы rphost) начинает отдавать клиентам устаревшие версии метаданных из оперативной памяти, игнорируя реальное физическое содержимое таблиц базы данных. Именно поэтому сравнение конфигураций выдает ложный вердикт об их идентичности.
Хранилище конфигурации оптимизирует сетевой трафик и скорость работы за счет кэширования объектов на локальном диске разработчика. Данный кэш хранится в профиле пользователя ОС. При регулярных динамических обновлениях и работе нескольких программистов локальный индекс Хранилища повреждается. Платформа перестает видеть реальные номера версий (версионирование «сбивается»), из-за чего затирание кода становится регулярным событием.
Если вы столкнулись с подобным поведением Хранилища и конфигурации, стандартное перезапуски баз не помогут. Требуется провести комплексную «терапию» системы. Выполним следующие шаги.
Первым делом необходимо полностью очистить кэш на стороне клиента (разработчика). Для этого закройте все сеансы 1С и Конфигуратора.
%userprofile%\AppData\Local\1C\1Cv8%userprofile%\AppData\Roaming\1C\1Cv828498f39-da92-4b2a-874b-e7b34f82bb55.%localappdata%\1C\1Cv8\<UID базы>\ConfigAndRules. Удалите эту директорию. При следующем подключении к Хранилищу платформа заново построит индекс версий, что исключит ошибку при захвате объектов.Зачастую старые версии модулей удерживаются в оперативной памяти рабочих процессов сервера 1С (rphost). Особенно это критично для регламентных заданий, фоновые процессы которых могут выполнять старый код неделями после динамического обновления.
1C:Enterprise 8.3 Server Agent).C:\Program Files\1cv8\srvinfo).reg_1541), зайдите в каталог проблемной информационной базы и удалите папки кэша (такие как snccntry и временные файлы сессий).Если очистка кэша сервера не помогла, и база данных продолжает находиться в состоянии «расщепления сознания» (когда запущенный сеанс видит один код, а Конфигуратор — другой), необходимо очистить служебные таблицы 1С на уровне СУБД.
Внимание! Перед выполнением любых запросов напрямую к СУБД обязательно сделайте резервную копию базы данных (бэкап средствами SQL Server).
Выполним следующий T-SQL скрипт в среде СУБД MS SQL Server для очистки зависших признаков динамического обновления:
-- Удаляем зависшие маркеры динамического обновления из таблицы Config
DELETE FROM [Имя_Вашей_Базы].[dbo].[Config] WHERE FileName = 'commit';
DELETE FROM [Имя_Вашей_Базы].[dbo].[Config] WHERE FileName = 'dbStruFinal';
DELETE FROM [Имя_Вашей_Базы].[dbo].[Config] WHERE FileName = 'DynamicallyUpdated';
DELETE FROM [Имя_Вашей_Базы].[dbo].[Config] WHERE FileName = 'dynamicCommit';
После выполнения данного скрипта сервер приложений 1С перечитает реальное состояние конфигурации из базы данных СУБД, и проблема ложной идентичности при сравнении конфигураций исчезнет.
Чтобы навсегда обезопасить себя и свою команду от потери исходного кода в Хранилище конфигурации, рекомендуем пересмотреть стандарты разработки и отказаться от устаревших методик.
Разработка непосредственно в рабочей базе, подключенной к Хранилищу — это грубейшее нарушение правил коллективной разработки. Рабочая база **никогда** не должна быть подключена к Хранилищу напрямую.
Правильная схема взаимодействия выглядит так:
.cf), который накатывается на рабочую базу в плановое технологическое окно.Если исправление критической ошибки требуется внести немедленно, и у вас нет возможности выгнать пользователей для монопольного обновления основной конфигурации, забудьте про динамическое обновление общего модуля.
Используйте механизм Расширений конфигурации:
&Вместо.Если масштаб вашей разработки велик, а в команде трудится более 3-5 программистов, классическое Хранилище конфигураций 1С становится узким горлышком. Рассмотрите переход на современную среду разработки 1C:Enterprise Development Tools (EDT) в связке с системой контроля версий Git.
Git полностью исключает проблему «тихой» перезаписи чужого кода. Если два разработчика изменят один и тот же общий модуль, Git физически не позволит выполнить слияние веток без ручного разрешения конфликта (Merge Conflict). Это гарантирует стопроцентную сохранность исходного кода и прозрачную историю изменений всей системы.