В практике администрирования 1С иногда возникает соблазн подключить одну и ту же базу данных, размещенную на SQL-сервере, к нескольким независимым серверам приложений 1С. Причины могут быть разными: желание разделить нагрузку между пользователями и фоновыми заданиями, тестирование новой версии платформы на рабочих данных или попытка организовать отказоустойчивость "своими руками". Однако, несмотря на то что технически консоль администрирования позволяет это сделать, такая конфигурация является критически опасной.
В этой статье мы подробно разберем, почему такая схема работы неизбежно приведет к логическому разрушению базы данных, и проанализируем технические аспекты взаимодействия платформы 1С с СУБД.
Рассмотрим главную проблему — систему блокировок. В современных конфигурациях 1С (начиная с версии 8.2) основным механизмом обеспечения целостности данных являются управляемые блокировки (Managed Locks). Проанализируем, как они работают: управляемая блокировка устанавливается не в самой базе SQL, а в памяти менеджера кластера 1С.
Представим ситуацию: у нас есть Сервер А и Сервер Б, подключенные к одной базе SQL. Когда пользователь на Сервере А начинает проводить документ, сервер 1С ставит управляемую блокировку на регистры, чтобы никто другой не мог изменить эти данные до завершения транзакции. Однако Сервер Б ничего не знает о блокировках, установленных на Сервере А, так как у них разные менеджеры кластера и они не обмениваются информацией о состоянии памяти.
Выясним причину опасности: если в это же время пользователь на Сервере Б попытается провести тот же документ или документ, затрагивающий те же остатки, Сервер Б разрешит это действие. В итоге мы получим ситуацию, когда два независимых процесса одновременно записывают данные в одни и те же таблицы SQL. Это приводит к:
Пример кода, который на одном сервере заблокирует данные, а на другом — нет:
Блокировка = Новый БлокировкаДанных;
ЭлементБлокировки = Блокировка.Добавить("РегистрНакопления.ОстаткиТоваров");
ЭлементБлокировки.УстановитьЗначение("Склад", СкладСсылка);
ЭлементБлокировки.Режим = РежимБлокировкиДанных.Исключительный;
Блокировка.Заблокировать();
// На Сервере А данные защищены, Сервер Б об этой блокировке не знает.
Проанализируем ситуацию, когда серверы имеют разные версии платформы (например, 8.3.22 и 8.3.23). Платформа 1С при запуске проверяет соответствие структуры таблиц SQL своим внутренним алгоритмам. Если более новая версия платформы обнаружит, что системные таблицы требуют обновления (например, таблицы расширений, конфигурации или итогов), она может автоматически изменить структуру БД без уведомления администратора.
Как только структура изменится под новую версию, старая версия платформы на втором сервере начнет работать некорректно. Это может выражаться в:
Разберем, как 1С работает с кэшем нумераторов. Для ускорения работы сервер 1С кэширует в своей памяти номера следующих создаваемых документов. Рассмотрим сценарий: Сервер А зарезервировал для реализации номера с 100 по 110. Сервер Б, не зная об этом, может зарезервировать те же самые номера. При попытке записи документа в базу данных SQL возникнет ошибка уникальности номера, либо (в худшем случае) один документ перезапишет другой, если механизмы контроля СУБД будут обойдены на уровне платформы.
Аналогичная проблема касается кэша метаданных. Изменения, внесенные в конфигурацию через один сервер, не будут подхвачены вторым сервером. В результате пользователи будут работать с разными версиями логики приложения, обращаясь к одной и той же структуре данных.
Посмотрим на работу регламентных заданий. Каждый сервер 1С имеет собственный планировщик. В штатной ситуации (один кластер) задания распределяются между рабочими серверами. В нашей же схеме оба сервера попытаются одновременно запустить, например, «Закрытие месяца» или «Пересчет итогов».
Поскольку оба сервера считают себя «главными» для этой базы, мы получим:
Deadlocks (взаимные блокировки) на уровне СУБД.Важно помнить, что не все данные 1С хранятся в SQL. Например, индексы полнотекстового поиска хранятся в рабочем каталоге кластера (на диске сервера приложений). Если два сервера работают с одной базой, их поисковые индексы мгновенно разойдутся. Пользователь на Сервере А не сможет найти документ, созданный на Сервере Б, пока не будет выполнено полное переиндексирование, которое, в свою очередь, будет мешать работе другого сервера.
Если ваша цель — отделить фоновые задания от работы пользователей или распределить нагрузку, необходимо использовать штатный механизм Кластера серверов 1С. Посмотрим, как это сделать правильно:
администрирование серверов 1С Предприятия).В этом случае в системе будет один Центральный менеджер кластера, который будет централизованно управлять:
Пример настройки требований назначения функциональности (концептуально):
// Для Сервера №1 (Рабочий):
Объект назначения: Клиентское соединение; Тип: Назначать.
Объект назначения: Фоновое задание; Тип: Не назначать.
// Для Сервера №2 (Фоновый):
Объект назначения: Фоновое задание; Тип: Назначать.
Объект назначения: Клиентское соединение; Тип: Не назначать.
Только такая схема является безопасной и поддерживаемой вендором. Любые попытки «обмануть» систему и подключить два независимых кластера к одной базе SQL закончатся потерей данных и отказом технической поддержки 1С в помощи, так как это является прямым нарушением регламентов эксплуатации системы.