Интеграция коробочного Битрикс24 с внешней базой данных строится двумя путями. Первый: обмен через REST API и вебхуки, когда порталу отдают готовые данные, а не доступ к таблицам. Второй: прямое подключение к сторонней СУБД, которое прописывается в секции connections файла /bitrix/.settings.php и вызывается из кода портала. Прямое подключение быстрее, но писать им в таблицы самого Битрикс24 нельзя.
Дальше картина, знакомая почти каждому владельцу коробки. Склад живёт в учётной системе, биллинг в собственной базе на PostgreSQL, отдел продаж сидит в Битрикс24, и менеджер держит в голове три окна сразу. Кто-то предлагает «просто подцепить базу напрямую», кто-то настаивает на обмене файлами по расписанию. Разницу между этими подходами считают в часах разработки, хотя важнее другое: сколько раз за год интеграция встанет после планового обновления портала.
Что такое внешняя база данных применительно к коробке
Внешняя база данных для портала: это любое хранилище за пределами основной базы Битрикс24, к которому портал обращается за данными или в которое он их отдаёт. Под определение попадают база 1С, отдельная база биллинга, аналитическое хранилище, база сайта на другой CMS, даже обычная MySQL-база с прайсами, которую поддерживает поставщик.
Сама коробка живёт на своей СУБД, и выбор здесь ограничен. В технических требованиях коробочного Битрикс24 указаны MySQL 8.x и PostgreSQL 11 и выше, причём PostgreSQL доступен только на лицензии «Энтерпрайз для Постгрес». Oracle и MSSQL не поддерживаются, PHP нужен версии 8.2 и выше. Это важно на старте: если внешняя система работает на MSSQL, речь пойдёт не о «подключим базу к порталу», а о промежуточном слое, который будет ходить в MSSQL своими средствами.
Облачный Битрикс24 к чужой базе подключить нельзя в принципе: там нет доступа к файлам конфигурации и нет своего кода на сервере. Всё, что доступно облаку, это REST. У коробки выбор шире, и именно поэтому её чаще берут компании с тяжёлым учётом. Проговорить это лучше до сметы, потому что половина споров о бюджете интеграции начинается с путаницы между двумя версиями продукта.
Когда прямое подключение оправдано, а когда хватит REST
Прямое подключение к внешней СУБД имеет смысл, когда данных много, они нужны быстро и в основном на чтение. Остатки по 40 тысячам позиций, история платежей за пять лет, справочник контрагентов на 200 тысяч записей: гонять такие объёмы через API дорого по времени и по нагрузке.
REST выигрывает в других ситуациях. Когда обмен событийный, а не объёмный: создали сделку, отправили заявку в учётную систему, получили номер заказа. Когда внешняя система в чужой зоне ответственности и её владелец не готов открывать доступ к базе. Когда интеграцию будет поддерживать не тот человек, который её написал, и понятный документированный интерфейс важнее скорости.
На проектах B2BPRO.KZ мы чаще всего видим гибрид: справочники и тяжёлые выборки читаются напрямую из внешней базы, а всё, что меняет данные, идёт через API внешней системы. Такое разделение экономит и ресурсы сервера, и нервы при разборе инцидентов, потому что записи в чужую базу из портала просто не существует.
У каждого второго подрядчика при этом возникает соблазн писать напрямую в таблицы Битрикс24 в обход API. Так делать нельзя. Структуру таблиц никто не обещал сохранять, она меняется между обновлениями, а вокруг записи в CRM живут события, индексы поиска, счётчики и бизнес-процессы, которые прямой INSERT не запустит. Сделка появится в базе и не появится в воронке. Разбирать такое в поддержке дольше, чем написать интеграцию заново.
Как подключить вторую базу: секция connections в .settings.php
Дополнительное подключение описывается в файле /bitrix/.settings.php, в секции connections. Рядом с подключением default, через которое работает сам портал, добавляется ещё одно, со своим именем. В описании настроек ядра 1С-Битрикс перечислены ключи, которые задаются для каждого подключения:
className: класс, реализующий работу с конкретным типом СУБД, например\Bitrix\Main\DB\MysqliConnection;host: адрес сервера базы, при необходимости с портом;database: имя базы;loginиpassword: учётные данные;options: флаги постоянного и отложенного соединения.
Флаг отложенного соединения полезнее, чем кажется. С ним портал не устанавливает связь с внешней базой на каждом хите, а делает это только когда к соединению реально обратились. Для интеграции, которая нужна в трёх местах из сотни, разница в нагрузке заметна.
Получить такое соединение из кода можно методом Application::getConnection(). Документация по методу описывает его прямо: он возвращает соединение с базой данных указанного имени, а при пустом параметре отдаёт соединение по умолчанию. То есть Application::getConnection('billing') вернёт объект \Bitrix\Main\DB\Connection для базы биллинга, и дальше с ним работают обычными запросами.
Файл .settings.php хранит логин и пароль от внешней базы открытым текстом, как и от основной. Поэтому у него всегда должны быть минимальные права на чтение и никакого попадания в репозиторий. Звучит очевидно, но мы регулярно находим копии конфигов в архивах внутри публичной директории сайта.
Как заставить ORM работать с чужой базой
Прямые SQL-запросы к внешней базе работают, но у D7 есть вариант аккуратнее. Класс сущности наследуется от DataManager, и в нём переопределяется метод getConnectionName(). Официальное описание метода говорит, что он возвращает имя соединения для сущности, и в примере из документации метод отдаёт строку с именем соединения, прописанным в настройках.
Внешняя таблица после этого перестаёт быть чужеродным куском кода. К ней применяются те же выборки с фильтрами и выражениями, те же типы полей, тот же кеш, что и к родным сущностям портала. Разработчику, который придёт на проект через год, не придётся разбирать ручные запросы со склеенными строками.
Сущность, описанная через DataManager, к тому же легко закрывается кешированием на уровне выборки, и внешняя база перестаёт получать одинаковые запросы десятки раз подряд. Для справочников, которые меняются раз в сутки, это снимает почти всю нагрузку. Срок жизни кеша подбирается по тому, насколько свежими данные должны быть для пользователя: остатки по складу живут минуты, справочник юридических лиц спокойно живёт часы.
Ограничение тоже есть, и его нужно закладывать в архитектуру. Связать одним запросом сущность из внешнего соединения и сущность из основной базы нельзя: СУБД разные, соединения разные, JOIN между ними невозможен. Данные собираются в коде: сначала выборка из одной базы, потом из другой по полученным идентификаторам. На больших объёмах это значит, что нужны нормальные индексы по полям связи с обеих сторон.
Чем отличается чтение на лету от зеркала данных
Чтение на лету означает, что портал обращается во внешнюю базу в момент, когда пользователь открыл карточку или список. Зеркало означает, что данные заранее скопированы в таблицы рядом с порталом, а пользователь работает с копией. Между этими крайностями есть промежуточный вариант с очередью событий. Выбор влияет на всё: на скорость, на поведение при аварии, на стоимость поддержки.
| Параметр | Чтение на лету | Зеркало (копия таблиц) | Очередь событий |
|---|---|---|---|
| Актуальность данных | Всегда текущая | По расписанию обмена | Близкая к текущей |
| Если внешняя база недоступна | Раздел не открывается | Портал работает на копии | События копятся, обмен догоняет |
| Нагрузка на внешнюю систему | Высокая, зависит от трафика | Низкая, всплески по расписанию | Средняя, равномерная |
| Сложность разработки | Низкая | Средняя | Высокая |
| Типовая задача | Справочники, остатки, история | Аналитика, отчёты, поиск | Заказы, статусы, платежи |
Ошибка, которая стоит дороже всего, это чтение на лету в тех местах портала, которые открываются постоянно. Остаток по товару в карточке сделки видят десять человек в день, и запрос во внешнюю базу здесь незаметен. Тот же остаток в списке из 50 сделок превращается в 50 запросов на каждое открытие списка, и внешняя система начинает отвечать медленно уже к обеду.
Что ломается чаще всего
Чаще всего разбираться приходится с кодировками и типами данных. Внешняя база на cp1251, портал на utf8mb4, и казахские буквы в названиях контрагентов превращаются в вопросительные знаки. Лечится заданием кодировки соединения на этапе подключения, но обнаруживается обычно после того, как данные уже уехали в отчёт.
Следом идут даты. Формат даты во внешней системе почти никогда не совпадает с тем, что ждёт портал, а часовой пояс сервера базы может отличаться от пояса портала. Для Казахстана это особенно заметно, когда внешняя система стоит в другой стране, и ночная смена складских операций попадает во вчерашний день отчёта.
Отдельная история с правами доступа. Интеграция собирается под учётной записью с широкими правами, а в продакшн уезжает под урезанной, и половина выборок возвращает пустоту без единой ошибки в логе. Отдельная учётная запись для портала, только на чтение и только на нужные таблицы, снимает и эту проблему, и половину вопросов безопасности.
Ещё одна частая беда: молчаливые таймауты. Если внешняя база отвечает дольше обычного, портал ждёт, страница висит, пользователь обновляет её ещё раз, запросов становится вдвое больше. Любое обращение во внешнюю систему нужно ограничивать по времени и оборачивать в обработку ошибок, чтобы раздел показывал понятное сообщение, а не белый экран.
А самая обидная поломка вообще не техническая. Владелец внешней системы меняет структуру таблицы, никого не предупредив, потому что для него это рядовая доработка. Портал в этот момент перестаёт видеть половину полей. Защищает здесь договорённость: письменный перечень таблиц и полей, на которые опирается интеграция, и обязанность предупреждать об изменениях в этом перечне. Технически подстраховаться помогают представления, за которыми структуру можно менять без последствий для портала.
Сколько занимает такая интеграция
Срок определяется не объёмом кода, а тем, насколько подготовлена внешняя сторона. Когда доступ к базе уже есть, структура описана и сценарии согласованы, связка справочника с порталом собирается за несколько рабочих дней. Когда доступ приходится выбивать у стороннего подрядчика, а структуру восстанавливать по именам полей, те же несколько дней разработки тонут в двух-трёх неделях переписки.
Поэтому смета честно делится на две части. Первая: обследование, где описываются таблицы, поля, объёмы и сценарии обмена. Вторая: собственно разработка и тестирование. Пропуск первой части ради скорости почти всегда возвращается переделкой, потому что ключевая деталь вроде отсутствия уникального идентификатора у записей внешней системы всплывает уже после того, как обмен написан.
Ещё один фактор: наличие тестового контура. Если внешняя система существует в единственном боевом экземпляре, проверять интеграцию придётся осторожно и медленно, а любые операции записи откладывать до полной уверенности. Создание тестовой копии внешней базы обычно окупается на первом же этапе отладки, и его стоит закладывать в план работ отдельной строкой.
Безопасность и сеть: что закрыть до запуска
Внешняя база не должна быть доступна из интернета. Нормальная схема выглядит так: сервер СУБД слушает только внутренний интерфейс, портал ходит к нему по закрытому каналу внутри сети или через VPN, а список разрешённых адресов ограничен. Если база физически в другом дата-центре, канал шифруется.
Учётная запись для портала создаётся отдельная, с правами только на те таблицы и представления, которые реально нужны. Права на запись выдаются, только если сценарий записи существует и описан. Хорошая практика для сложных случаев: вместо доступа к таблицам дать порталу доступ к представлениям, за которыми владелец внешней системы может менять структуру, не ломая интеграцию.
Отдельно продумывается, что произойдёт при смене пароля на стороне внешней системы. Пароль в .settings.php меняется руками, и если об этом узнают только по жалобам пользователей, простой растянется на день. Поэтому доступность внешнего соединения ставится на мониторинг вместе с остальными проверками портала. Если внутренней команды для этого нет, такие проверки закрывает внедрение и сопровождение Битрикс24 на стороне партнёра: мы ведём коробочные порталы с контролем доступности интеграций, а не только самого сайта.
Порядок работ: пошаговый план
- Описать, какие именно данные нужны порталу и в какую сторону они идут: список таблиц, полей и сценариев вместо формулировки «интеграция со складом».
- Проверить совместимость: тип и версия внешней СУБД, сетевая доступность, кодировка, часовой пояс.
- Выбрать схему обмена по таблице выше и зафиксировать её письменно вместе с владельцем внешней системы.
- Создать на стороне внешней базы отдельную учётную запись с минимальными правами и, при необходимости, представления для портала.
- Добавить соединение в секцию
connectionsфайла/bitrix/.settings.phpи проверить его на тестовой копии портала, а не на боевом. - Описать сущности через
DataManagerс переопределённымgetConnectionName()и закрыть обращения к ним обработкой ошибок и ограничением по времени. - Прогнать нагрузочный сценарий: не одна карточка, а список из полусотни записей и одновременная работа нескольких пользователей.
- Поставить на мониторинг доступность соединения и время ответа, завести оповещение на ответственного.
- Записать всё в документацию проекта: имя соединения, учётную запись, список таблиц, порядок действий при смене пароля.
Что учесть при обновлении коробки
Интеграция с внешней базой не отменяет обновлений портала, но повышает цену ошибки. Обновление сначала прокатывается на копии, где внешнее соединение настроено на тестовую базу, и только потом на боевом. Если такой копии нет, её стоит завести до интеграции, а не после первого инцидента.
Собственный код под интеграцию должен жить в отдельном модуле или в /local/, а не правками в ядре. Код, вписанный в файлы дистрибутива, исчезает при первом же обновлении, и восстанавливать его приходится по памяти.
Проверочный список после каждого обновления короткий: соединение поднимается, тестовая выборка возвращает данные, даты и кодировка на месте, время ответа не выросло. На это уходит пять минут, а без такой проверки инцидент обычно всплывает через неделю и разбирается целый день. Если поддерживать это некому, рутину проще передать партнёру вместе с остальным сопровождением портала: мы в B2BPRO.KZ ведём такие проверки регламентом, а не по факту жалоб.
Частые вопросы
Можно ли подключить внешнюю базу к облачному Битрикс24?
Нет. В облаке нет доступа к файлам конфигурации портала и нет возможности выполнять свой серверный код, поэтому подключение к сторонней СУБД там невозможно в принципе. Для облака остаётся обмен через REST API и вебхуки: внешняя система сама отдаёт порталу готовые данные и забирает нужные ей. Прямое подключение к базе доступно только коробочной версии.
Сколько внешних баз можно подключить к одному порталу?
Технически количество подключений в секции connections не ограничено какой-то одной цифрой, каждое описывается своим именем и своими параметрами. На практике ограничение другое: каждое соединение это ресурсы сервера и ещё одна точка отказа. Если баз больше двух-трёх, разумнее собрать данные в одно промежуточное хранилище и подключать портал уже к нему.
Можно ли писать данные напрямую в таблицы Битрикс24?
Делать этого нельзя. Структура таблиц портала меняется между обновлениями, а вокруг создания сделки или контакта работают события, индексы поиска и бизнес-процессы, которые прямой запрос в базу не запускает. Запись в портал выполняется только через API: REST для внешних систем и методы D7 для кода на сервере. Читать из базы напрямую для отчётов допустимо, писать нет.
Что делать, если внешняя система работает на MSSQL?
Коробочный Битрикс24 не поддерживает MSSQL и Oracle как свою СУБД, но это не значит, что интеграция невозможна. Обычно ставится промежуточный слой: небольшой сервис, который читает MSSQL своими средствами и отдаёт порталу данные по HTTP, либо регулярно выгружает нужные таблицы в базу, к которой портал уже умеет подключаться. Схему выбирают по объёму данных и требуемой свежести.
Как понять, что интеграция тормозит именно из-за внешней базы?
Первый признак: медленно открывается только тот раздел, где выводятся внешние данные, а остальной портал отзывается нормально. Проверяется это замером времени ответа внешней базы отдельно от портала и подсчётом количества запросов на одно открытие страницы. Чаще всего выясняется, что в списке выполняется по запросу на каждую строку, и проблема лечится одной выборкой с кешированием.
