В статье рассматриваются текущие возможности горизонтального масштабирования СУБД для 1С, а также какое решение предлагает Tantor Postgres.
Горизонтальное масштабирование и текущие ограничения 1С
Горизонтальное масштабирование — это подход к увеличению производительности системы путем добавления новых серверов вместо наращивания мощностей существующих. Это позволяет распределять нагрузку между множеством узлов и практически неограниченно расширять вычислительные ресурсы. В 1С этот подход реализован только лишь частично: платформа 1С поддерживает кластеризацию серверов приложений, что позволяет запускать несколько серверов 1С:Предприятие для параллельной обработки запросов пользователей и выполнения бизнес-логики. Например, на отдельные серверы приложений часто выносят отчеты и тяжелые регламентные операции, чтобы они не влияли на основную работу пользователей. Это помогает справляться с возросшей нагрузкой: когда одновременно работают тысячи пользователей, задачи распределяются между серверами кластера, и система остаётся отзывчивой.
Однако критическое ограничение состоит в том, что все серверы приложений 1С работают с единой базой данных, которая и становится узким местом всей системы. СУБД — будь то MS SQL Server или PostgreSQL — остаётся единой точкой входа для всех операций чтения и записи, и именно здесь при росте нагрузки происходит основное замедление. Реляционные базы данных по своей природе горизонтально масштабируются сложно из-за необходимости поддержания целостности данных, управления распределёнными транзакциями и координации блокировок между узлами. В результате — сколько бы серверов приложений вы ни добавили в кластер 1С, все они будут конкурировать за доступ к одной и той же базе данных, конкурируя за ее ресурсы. Таким образом, горизонтальное масштабирование в 1С работает лишь на уровне прикладной логики, но не решает фундаментальную проблему масштабирования слоя хранения данных.

Механизм копий баз данных
Начиная с версии 8.3.14, в платформе 1С появился механизм копий баз данных. Он позволяет распределять нагрузку на чтение между несколькими экземплярами базы данных, где одна база выступает главной (принимает все операции записи), а остальные являются её репликами и могут обслуживать часть запросов на чтение. Платформа поддерживает два типа репликации: стандартную и внешнюю. Стандартная репликация реализуется средствами самой платформы 1С — сервер приложений самостоятельно отслеживает изменения в главной базе и периодически синхронизирует данные с копиями, что даёт платформе полный контроль над процессом, но требует дополнительных ресурсов сервера 1С и вызывает некоторую задержку в актуальности данных. Внешняя репликация, напротив, полностью полагается на встроенные механизмы репликации СУБД — для PostgreSQL это streaming replication, для MS SQL Server — Always On или Log Shipping, а платформа 1С лишь использует готовые реплики, направляя на них операции чтения.
По сути тип репликации "стандартный" — это логическая репликация, а "внешний" — физическая. Преимущество внешней репликации заключается в том, что она работает на уровне блоков данных или журнала транзакций СУБД, обеспечивая практически мгновенную синхронизацию с минимальной задержкой, в то время как стандартная репликация 1С работает на уровне прикладных данных и синхронизирует изменения дискретно с заметными интервалами. Кроме того, внешняя репликация не нагружает сервер приложений 1С дополнительной работой по отслеживанию и переносу изменений: вся тяжесть ложится на СУБД, которая оптимизирована именн�� для этой задачи. У компаний, которым этот функционал может быть полезен, всегда есть реплики, и использование внешней репликации для них наиболее оптимально, ведь нет необходимости поднимать логические копии базы данных, обслуживать их, поддерживать в актуальном состоянии и т.д. К тому же мощности серверов, где находятся реплики, как правило, простаивают, так почему бы не утилизировать ради столь благих намерений? Однако использование внешней репликации PostgreSQL накладывает существенное ограничение: на read-only реплике PostgreSQL невозможно создавать временные таблицы, а платформа 1С активно использует их для выполнения сложных запросов, построения отчётов и обработки данных.
Это означает, что при внешней репликации PostgreSQL часть запросов, требующих создания временных структур, не сможет быть выполнена на копии и будет автоматически перенаправлена на главную базу, а это снизит эффективность распределения нагрузки и, по сути, сделает механизм нерабочим, поскольку большая часть запросов 1С будет использовать временные таблицы. MS SQL Server в этом плане более гибок — его реплики Always On позволяют создавать временные объекты в tempdb, что делает внешнюю репликацию на SQL Server более привлекательным вариантом для 1С.

При этом на реплике могут быть выполнены не все запросы, а только те, которые удовлетворяют таким условиям:
Запрос выполняется с помощью объекта Запрос или при работе с системой компоновки данных;
Запрос выполняется вне транзакции;
В объекте Запрос не используется менеджер временных таблиц.
Проблема и ее решение в Tantor Postgres
Давайте посмотрим, в чем заключается проблема с выполнением запросов на реплике Read Only. Если выполнить на ней запрос создания временной таблицы (а 1С постоянно создает временные таблицы) и индекса к этой таблице...
|
...то мы получим ошибку:
|
PostgreSQL запрещает выполнение DDL-команд на реплике, в том числе и команды, связанные с созданием временных таблиц. Казалось бы, временная таблица существует недолго и на данные в самой базе никак не влияет, так почему бы не разрешить ее создание, удаление? Все дело в том, что создание временных объектов (таблиц, индексов) затрагивает 13 таблиц системного каталога. Посмотрим, что произошло в основных из них при выполнении вышеприведенной команды:
pg_class —хранит информацию о названии всех таблиц, а также их внутренних идентификаторах (oid). В нашем случае была бы добавлена информация о таблице "tt1";pg_attribute —хранит информацию о всех полях таблиц. В нашем случае была бы добавлена информация о поле "_q_001_f_000rref" таблицы "tt1";pg_type —хранит информацию о типах полей таблиц. В нашем случае была бы добавлена информация, что поле "_q_001_f_000rref" имеет тип "bytea";pg_index —хранит информацию о созданных индексах. В нашем случае была бы добавлена информация об индексе "tmpind_0";pg_depend —хранит информацию о зависимостях между объектами БД. В нашем случае была бы добавлена информация о том, что индекс "tmpind_0" относится к таблице "tt1";...и т.д.
То есть, создание временных объектов изменяет данные! Если бы PostgreSQL разрешил изменять таблицы системного каталога на реплике при создании временных объектов, это привело бы к следующим проблемам:
Разница в данных между мастером и репликой. Системный каталог на реплике содержал бы записи о временных объектах, которых нет на мастере, что нарушило бы фундаментальный принцип репликации: реплика должна быть точной копией мастера;
Конфликты при применении WAL-записей. Механизм streaming replication последовательно применяет WAL-записи с мастера на реплику, и если реплика генерирует собственные изменения в системном каталоге, это создаёт конфликты при применении входящих изменений, делая невозможным гарантировать консистентность данных;
Коллизии внутренних идентификаторов объектов (OID). Если бы реплика начала создавать свои объекты с собственными OID, возник бы риск коллизий с объектами, создаваемыми на мастере и реплицируемыми позже;
Блокировки критических страниц системных таблиц. Временные объекты на реплике могли бы заблокировать страницы системных таблиц (pg_class, pg_attribute и других), из-за чего реплика не смогла бы применить изменения из WAL мастера, и репликация остановилась бы с ошибкой конфликта.
Начиная с версии 17.5, в СУБД Tantor Postgres появился параметр enable_temp_memory_catalog, который позволяет создавать временные объекты без изменения таблиц системного каталога. При включении этого параметра информация о метаданных временных объектов хранится в локальной памяти каждого соединения к СУБД, а не в общем системном каталоге. Это меняет подход к работе с временными объектами и помогает решить как проблемы, описанные выше, так и улучшить вообще производительность системы (более подробно можно прочесть здесь).
Мы проектировали данную функциональность с прицелом на будущее, понимая возможности, которые откроет реализация. Давайте посмотрим, как это работает!
Настраиваем копию базы данных
Для начала нужно настроить копию баз данных в 1С. Делается это через пункт меню "Функции для технического специалиста" – "Стандартные" – "Управление копиями базы данных". Создаем новый элемент и заполняем его следующим образом:

В блоке 1 вводим название элемента, путь к базе на реплике и параметры аутентификации. Галку "Встроенный дата акселлератор" не ставим, т.к. используем существующую базу данных.
В блоке 2 выделяем все метаданные, а в блоке 3 не трогаем ничего, оставляем все по умолчанию.
Нажимаем "ОК" и получаем вопрос:

Здесь нужно нажать "Сохранить как есть". После этого элемент запишется и в форме списка у него будет Состояние = Включена:

Копия баз данных со стороны 1С готова к использованию!
Предупреждение о размещении копии
Выше при сохранении элемента копии БД мы получили предупреждение: БД уже используется информационной базой.
В платформе 8.3.26 в этом случае использование копии БД было невозможным, поскольку она сразу после записи переходила в состояние "Отключена", и обойти эту проверку было невозможным. Даже если создать новую базу на стороне СУБД, о которой сервер приложений 1С ничего не знает, ошибка все равно будет возникать. А вот в платформе 8.3.27 предупреждение выдается, но после записи использование копии БД возможно, поскольку она не отключается.
Также необходимо установить дополнительные параметры на реплике Tantor Postgres:
|
Разберем, что значат эти настройки, и как они влияют на работу 1С.
Параметр enable_temp_table_on_replica снимает ограничение на создание временных таблиц и индексов на реплике. Работает совместно с рассмотренным выше параметром enable_temp_memory_catalog.
Параметр hot_standby_feedback нужен для того, чтобы мастер получал от реплики состояние активных транзакций на чтение. Эта информация нужна мастеру для того, чтобы отложить удаление мертвых строк процессом autovacuum до тех пор, пока эти строки еще могут быть нужны активным запросам на реплике. Если этого не сделать, при активной работе пользователей будем получать следующую ошибку при выполнении запросов на реплике:
|
Параметр max_standby_streaming_delay определяет время, на которое реплика может задержать применение WAL-записей, если их применение вызовет конфликт с выполняющимися на реплике запросами на чтение. Например, в записях WAL пришло удаление строки в таблице, которое конфликтует с активным запросом на чтение из этой таблицы. Если за 300 секунд данный активный запрос не выполнится, то он вызовет упомянутую выше ошибку.
На этом с настройкой мы закончили. Давайте теперь перейдем к нагрузочным тестам, чтобы продемонстрировать все возможности.
Нагрузочное тестирование
Для получения объективных результатов мы подготовили тестовый стенд, максимально приближенный к реальным условиям промышленной эксплуатации высоконагруженных систем:
Роль сервера | ОС | Версия ПО | Модель CPU | Кол‑во CPU | Кол‑во RAM (ГБ) |
Сервер лицензирования 1С | Astra Linux 1.7.5 | 1С Предприятие 8.3.27.1719 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 4 | 16 |
Сервер приложений 1С | Astra Linux 1.7.5 | 1С Предприятие 8.3.27.1719 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 32 | 126 |
Сервер приложений 1С | Astra Linux 1.7.5 | 1С Предприятие 8.3.27.1719 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 32 | 126 |
Сервер приложений 1С | Astra Linux 1.7.5 | 1С Предприятие 8.3.27.1719 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 32 | 126 |
Сервер СУБД master | Astra Linux 1.8.1 | Tantor SE 1C 18.1.0 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 48 | 512 |
Сервер СУБД replica | Ubuntu 22.04 | Tantor SE 1C 18.1.0 | Intel(R) Xeon(R) Gold 6248R CPU @ 3.00GHz | 32 | 126 |
Кластер серверов 1С состоял из одного центрального и двух рабочих серверов. Отдельно был поднят сервер лицензирования 1С: все клиентские и серв��рные лицензии вынесены на него. Кластер СУБД состоял из двух серверов: один – под мастер, другой – под реплику. Ресурсы на реплике — скромнее по сравнению с мастером.
СУБД Tantor Postgres для 1C была настроена согласно нашим рекомендациям. Для нагрузочных тестов были выбраны две конфигурации: Документооборот и ERP. Рассмотрим характеристики этих баз, профиль нагрузки и результаты тестов более подробно.
Нагрузочный тест Документооборот
Конфигурация – Документооборот 2.1, размер базы — 210 Гб. Эмулируется работа 1000 пользователей, длительность теста – 3 часа, за это время пользователи выполняют 80 тысяч ключевых операций.
Профиль нагрузки — смешанный:
50% — открытие форм списков и документов, проведение документов, запись справочников;
30% — формирование отчетов;
20% — работа с обработками.
Первый запуск теста делаем без использования копии БД, чтобы оценить нагрузку на мастер. График нагрузки на CPU на мастере:

(Графики утилизации RAM и диска не приводим, т.к. они коррелируют с графиком CPU, и для демонстрации распределения нагрузки достаточно только графика по CPU)
Теперь настроим копию БД и запустим тест еще раз. Нагрузка распределится следующим образом.
Мастер:

Реплика:

Почему почти вся нагрузка ушла на реплику? Дело в том, что у всех отчетов на СКД по умолчанию стоит "Использование копий базы данных = Авто":

В этом случае платформа 1С будет все такие отчеты выполнять на работающих копиях БД при соблюдении требуемой актуальности данных. А для внешнего типа репликации платформа 1С считает, что данные в такой копии всегда актуальны. Поэтому все наши отчеты и выполнялись на реплике. И несмотря на то, что в профиле нагрузки только 30% операций были связаны с отчетами, получается, они в основном и нагружают СУБД в данном нагрузочном тесте.
В целях эксперимента мы сделали еще один тест, в котором в половине отчетов было запрещено их выполнение на копии базы данных, т.е. они всегда выполнялись на мастере.
Мастер:

Реплика:

В этом случае распределение нагрузки между серверами получилось более равномерное. По итогам нагрузочного теста APDEX при использовании копии БД стал лучше на 1%, т.е. был в пределах погрешности. Таким образом, способ разнесения нагрузки работает. Давайте теперь проверим, как он себя покажет на тесте ERP.
Нагрузочный тест ERP
Данный нагрузочный тест идет в комплекте типовой конфигурации ERP, и его можно скачать с сайта фирмы "1С".
Конфигурация – ERP2.5, размер базы — 1273 Гб. Эмулируется работа 2000 пользователей, длительность теста – 10 часов, т.е. эмулируем полноценный рабочий день. За это время пользователи выполняют 847 тысяч ключевых операций.
Профиль нагрузки — смешанный:
60% — открытие форм списков и документов, проведение документов, запись справочников;
5% — формирование отчетов;
35% — работа с обработками, различные расчеты.
В этом тесте также запускается процедура закрытия месяца.
Первый запуск теста делаем без использования копии БД, чтобы оценить нагрузку будет на мастер. График нагрузки на CPU на мастере:

При использовании копии БД настройки отчетов не менялись, т.е. в данном тесте стараемся по максимуму вынести все отчеты на реплику.
В отличие от теста на базе Документооборот, на этом тесте при использовании механизма копий БД мы столкнулись с несколькими проблемами в связи с более интенсивной OLTP-нагрузкой. Например, выполнение запроса на реплике приводило к ошибке:
|
Что получит пользователь при выполнении отчета, запрос которого привел к такой ошибке? Если в отчете стоит "Использование копий базы данных = Авто", отчет автоматически будет переформирован на мастере, и пользователь ничего не заметит. Если "Использование копий базы данных = Использовать только копии", отчет сформирован не будет, и пользователю будет выведена ошибка.
При этом сама копия БД при возникновении ошибки выполнения запроса на реплике будет отключена:

После исправления первопричин проблемы ее можно включить заново, просто перезаписав элемент копии базы данных.
После того, как возникшие ошибки были исправлены разработчиком СУБД, мы снова запустили тест, и он завершился успешно. Давайте посмотрим, как распределилась нагрузка.
Мастер:

Реплика:

По графикам видно, что в данном нагрузочном тесте нагрузка, создаваемая отчетами, не так велика, как в предыдущем тесте. Но было важно проверить, что при сильно возросшей OLTP-нагрузке механизм тоже будет работать корректно.
По итогам нагрузочного теста APDEX при использовании копии БД остался на том же уровне, как и без ее использования. То есть основная задача выполняется на отлично: нагрузка разносится без потери производительности.
Особенности использования копии БД
По итогам тестов можно обозначить важные моменты, которые нужно учитывать при использовании данного механизма:
Копия базы данных с типом репликации "Внешняя" всегда считается актуальной платформой 1С, но по факту реплика может получать данные от мастера с задержкой, и ��з-за этого при выполнении на мастере и реплике данные отчетов могут отличаться. В наших тестах задержка репликации была не более нескольких мегабайт, контролировать ее удобно с помощью раздела Репликация Платформы Tantor;
По умолчанию во всех отчетах стоит режим, который будет использовать копию БД, и все эти отчеты на СКД будут выполняться на реплике. Но с учетом п.1 нужно обдуманно подходить к выбору отчетов, которые можно выполнять на реплике с учетом требуемой актуальности данных в отчетах;
Если во время выполнения запроса на копии БД возникнет ошибка, то такая копия будет отключена, и выполнение запросов продолжится на мастере;
Отчеты, в запросах которых используются метаданные, измененные в расширении (например, по таблице документа document1293 создана таблица document1293x1), не могут быть выполнены на копии БД. Это ограничение платформы 1С. Надеемся, это ограничение будет снято, т.к. для логической репликации (стандартный тип репликации механизма копий БД) оно, быть может, и имеет смысл, но для физический репликации (внешний вид репликации) – не имеет, поскольку DDL-команды создания новых таблиц успешно реплицируются механизмом потоковой репликации;
В версии 8.3.27 появился новый метод платформы ПолучитьИнформациюОКопии(), который позволяет получить дополнительную информацию об используемой копии БД, например, ОшибкаПричиныОтключения. В ходе отладки механизма нагрузочными тестами нам это помогало быстро выяснить причину, по которой копия БД отключалась.
Заключение
Рассмотренный механизм действительно позволяет разносить нагрузку без каких-либо дополнительных накладных расходов, что дает возможность вместо вертикального масштабирования использовать горизонтальное и экономить ресурсы компании. Функциональность станет доступна в релизе Tantor Postgres 18. В ходе тестирования мы столкнулись и успешно решили несколько проблем, которые мешали механизму работать так, как показано выше в результатах нагрузочных тестов. При выпуске новых релизов мы всегда проводим целый ряд нагрузочных тестов на типовых конфигурациях 1С, чтобы убедиться, что производительность наших решений находится на высоком уровне и в логике работы СУБД нет ошибок.