В процессе администрирования и разработки распределенных информационных баз (РИБ) на платформе 1С:Предприятие 8.3 специалисты часто сталкиваются со специфическими сбоями при обновлении конфигурации. Один из наиболее коварных и труднодиагностируемых сбоев связан со странным поведением журнала регистрации. В логах системы фиксируется ошибка: Информационная база. Ошибка изменения конфигурации базы данных. Однако сразу же за ней следуют записи о том, что регистрация конфигурации изменена и обновление успешно завершено динамически. В интерфейсе пользователя при этом не возникает никаких предупреждений, но измененные метаданные перестают выгружаться в периферийные узлы РИБ.
В этой статье мы подробно проанализируем причины возникновения данной проблемы, разберем физику происходящих в СУБД процессов и рассмотрим несколько надежных практических способов восстановления корректной синхронизации метаданных между узлами РИБ.
Описанная ситуация чаще всего проявляется на платформе версии 8.3.13 (например, на релизе 8.3.13.1513) и связана с механизмом обработки неявного отката блокировок СУБД при обновлении базы данных. Давайте разберем по шагам, что происходит внутри системы в этот момент.
Когда администратор или программист запускает обновление конфигурации базы данных нажатием клавиши F7, платформа инициирует транзакцию и пытается монопольно заблокировать служебные таблицы метаданных. Если в этот момент на сервере выполняется фоновое регламентное задание, завис спящий сеанс пользователя или активен фоновый процесс СУБД, монопольная блокировка отклоняется сервером баз данных.
Из-за внутренней ошибки платформы в обработке исключений система фиксирует первичный отказ в монопольном доступе и записывает в журнал сообщение об ошибке изменения конфигурации. Однако вместо того, чтобы полностью прервать операцию и вернуть конфигурацию в исходное состояние, платформа ошибочно пытается применить изменения динамически, «на лету». В результате программный код (модули, формы) обновляется, а физическая структура таблиц СУБД и таблицы регистрации изменений для планов обмена РИБ остаются в рассинхронизированном состоянии.
Для распределенной информационной базы это имеет катастрофические последствия:
v8de:Config.КонфигурацияИзменена() возвращает значение Ложь, и подчиненная база продолжает функционировать на старой конфигурации. При первой же попытке записать данные новых типов или обратиться к новым реквизитам система падает с критической ошибкой несоответствия конфигурации ожидаемой.Самым простым и быстрым решением, которое помогает в большинстве случаев, является полная очистка кэша сервера приложений 1С в сочетании с временным отключением регламентных заданий. Обычная очистка клиентского кэша на рабочих станциях здесь не поможет, так как некорректные метаданные кэшируются именно на стороне сервера «1С:Предприятие».
Рассмотрим пошаговый алгоритм выполнения этой процедуры:
1C:Enterprise 8.3 Server Agent и нажать кнопку «Остановить».C:\Program Files\1cv8\srvinfo (или путь, указанный в параметрах запуска службы).reg_1541) временные каталоги кэша сеансов с именем snccntry, а также папки с уникальными идентификаторами баз данных (UUID), внутри которых содержатся временные файлы.snccntry и временные файлы баз данных. Внимание! Не удаляйте файлы конфигурации самого кластера (такие как 1CV8Reg.lst), чтобы не сбросить настройки списка баз данных и права доступа.1C:Enterprise 8.3 Server Agent обратно.Если кэш очищен, но база данных застряла в промежуточном состоянии и конфигуратор упорно продолжает предлагать динамическое обновление при каждой попытке монопольного изменения, проблему необходимо решать на уровне СУБД SQL. В клиент-серверном варианте работы конфигурация хранится в двух основных служебных таблицах:
dbo.Config — хранит рабочую конфигурацию базы данных, под управлением которой работают пользователи;dbo.ConfigSave — хранит конфигурацию, которая редактируется разработчиком в конфигураторе до момента сохранения и применения изменений.При сбое динамического обновления в таблице dbo.Config зависают записи со статусом изменений, содержащие в имени файла ключевое слово commit. Выясним, как принудительно удалить эти записи с помощью SQL-запроса.
Важно: Перед выполнением любых прямых манипуляций с базой данных на уровне СУБД обязательно сделайте резервную копию (бэкап) базы данных средствами Microsoft SQL Server или PostgreSQL!
Выполните следующий SQL-запрос к вашей базе данных через среду управления СУБД (например, SQL Server Management Studio):
DELETE FROM dbo.Config
WHERE FileName LIKE '%commit%';
Этот запрос принудительно удаляет признаки незавершенного «демонического» обновления. После успешного выполнения запроса откройте конфигуратор 1С и выполните обычное монопольное обновление конфигурации базы данных с помощью клавиши F7. Это вернет базу данных в стабильное состояние.
Что делать, если конфигурация в главном узле успешно обновилась, но периферийные узлы по-прежнему не получают файлы обновления метаданных через каналы РИБ? Существует надежный способ заставить платформу принудительно пересчитать хэш-сумму конфигурации и заново зарегистрировать изменения для планов обмена без необходимости отвязывать подчиненные узлы.
Проанализируем этот метод по шагам:
БуферОбновления и типом данных Строка (длиной 10 символов) или новый пустой справочник. Главное — изменить структуру метаданных.БуферОбновления) можно будет аналогичным образом удалить из главного узла при следующем плановом обновлении.Если стандартные механизмы обмена повреждены слишком сильно и файлы конфигурации упорно отказываются мигрировать в подчиненные узлы, можно воспользоваться классическим «альтернативным» методом ручной синхронизации. Этот метод заключается во временном отключении связи подчиненного узла с главным.
Рассмотрим алгоритм реализации этого метода:
.cf (например, main_node.cf).
// Отключение связи с главным узлом РИБ
ПланыОбмена.УстановитьГлавныйУзел(Неопределено);
После выполнения этого кода подчиненный узел становится самостоятельной информационной базой, и возможность изменения его конфигурации разблокируется.
main_node.cf.
// Восстановление связи с главным узлом РИБ
ГлавныйУзелСсылка = ПланыОбмена.НайтиПоКоду("КодГлавногоУзла");
Если ЗначениеЗаполнено(ГлавныйУзелСсылка) Тогда
ПланыОбмена.УстановитьГлавныйУзел(ГлавныйУзелСсылка);
КонецЕсли;
После восстановления связи структура конфигураций главного и подчиненного узлов станет абсолютно идентичной, и последующие сеансы обмена данными будут проходить в штатном режиме.
Чтобы минимизировать риски возникновения подобных сбоев в будущем, рекомендуем придерживаться нескольких простых административных правил: