База данных 1С-Битрикс - PostgreSQL, Redis, memcached, шардинг
Когда одной базы MySQL перестаёт хватать, у платформы есть несколько независимых осей масштабирования: другая СУБД, вынос кеша и сессий в память, ускорение чтения и распределение таблиц. Все бэкенды подключаются единообразно - через одну секцию конфигурации.
Как это работает
Единая точка конфигурации. Все подключения описываются в файле
/bitrix/.settings.php, в секции connections. Каждое подключение - именованный
массив, где ключ className определяет бэкенд. Подключение по умолчанию
называется default, остальные добавляются рядом под своими именами. В коде их
берут через Application::getConnection($name).
Драйверы под разные хранилища. Для MySQL это MysqliConnection, для
PostgreSQL - PgsqlConnection. Дополнительно поддерживаются MS SQL и Oracle. В
памяти работают MemcacheConnection, MemcachedConnection, RedisConnection и
HsphpReadConnection для HandlerSocket. Прикладной код обращается к ним
одинаково.
Четыре независимых оси масштабирования.
- Смена СУБД. PostgreSQL доступен по отдельной лицензии и даёт другой профиль нагрузки на крупных инсталляциях.
- Кеш и сессии в памяти. Redis умеет кеш, сессии и очереди задач, memcached - только кеш. Оба снимают нагрузку с основной базы.
- HandlerSocket. Протокол прямого доступа к данным MySQL в обход разбора SQL, ускоряет массовые выборки. Только чтение.
- Шардинг. Распределение таблиц по серверам.
Почему D7-код переносим, а прямой SQL - нет. Модули, работающие через ORM, переезжают между MySQL и PostgreSQL без доработок: за диалект отвечает помощник SQL конкретного соединения. А вот прямые запросы с обратными кавычками и специфичными для MySQL функциями при смене базы ломаются и требуют ручной переработки.
Важное ограничение коробки. Из шардинга доступен только вертикальный и только для модулей веб-аналитики и поиска. Горизонтального шардинга платформа не предоставляет. PostgreSQL требует специальной лицензии, а хранилища в памяти доступны без лицензионных ограничений.
Примеры
1. Дополнительное подключение
'connections' => [ 'value' => [ 'default' => [ 'className' => '\\Bitrix\\Main\\DB\\MysqliConnection', 'host' => '10.0.0.10', 'database' => 'sitemanager', 'login' => 'bitrix', 'password' => '...', 'options' => 2, // отложенное соединение ], 'analytics' => [ 'className' => '\\Bitrix\\Main\\DB\\MysqliConnection', 'host' => '10.0.0.11', 'database' => 'analytics', 'login' => 'bitrix', 'password' => '...', 'options' => 2, ], ], 'readonly' => true,],$connection = \Bitrix\Main\Application::getConnection('analytics');$rows = $connection->query('SELECT ...')->fetchAll();Флаги режима соединения складываются: единица означает постоянное соединение, двойка - отложенное, которое устанавливается только при первом запросе. Для базы обычно используют отложенное.
Сущность ORM можно привязать к другому соединению, переопределив метод
getConnectionName(). Учтите, что транзакция в этом случае работает только в
рамках своего соединения.
2. Кеш и сессии в памяти
'cache' => [ 'value' => [ 'type' => 'redis', 'redis' => [ 'host' => '127.0.0.1', 'port' => 6379, ], ],],Вынос кеша из файловой системы в память - одно из самых заметных по эффекту изменений на нагруженном сайте: исчезают тысячи мелких файловых операций. Redis дополнительно умеет хранить сессии и очереди.
3. Совместимый с PostgreSQL код
// ПЛОХО: обратные кавычки и двойные кавычки как строка$sql = 'SELECT `NAME` FROM b_iblock WHERE CODE = "news"';
// ХОРОШО: через помощник SQL$helper = \Bitrix\Main\Application::getConnection()->getSqlHelper();$sql = 'SELECT ' . $helper->quote('NAME') . ' FROM b_iblock WHERE CODE = \'' . $helper->forSql('news') . '\'';Правила совместимости, которые чаще всего нарушают:
- В PostgreSQL двойные кавычки - это идентификатор, а не строка. Строковый литерал берут в одинарные кавычки, а лучше прогоняют через экранирование.
- Обратные кавычки MySQL PostgreSQL не понимает вовсе.
- Не квотируйте идентификаторы без необходимости: в PostgreSQL явно закавыченный идентификатор становится регистрозависимым, и код, ожидающий верхний регистр, перестаёт находить колонку.
- Имена индексов в PostgreSQL уникальны в пределах схемы, а не таблицы - одинаковые имена на разных таблицах конфликтуют.
- Модификатора
unsignedв PostgreSQL нет.
Самый надёжный способ не столкнуться со всем этим - писать через ORM.
Справочник
| Элемент | Назначение | Особенности |
|---|---|---|
секция connections | описание всех подключений | закрывают флагом только для чтения |
Application::getConnection($name) | получение подключения | без аргумента - подключение по умолчанию |
MysqliConnection / PgsqlConnection | драйверы основных СУБД | PostgreSQL требует отдельной лицензии |
RedisConnection | Redis | кеш, сессии, очереди |
MemcachedConnection | memcached | только кеш |
HsphpReadConnection | HandlerSocket | только чтение, в обход разбора SQL |
options | режим соединения | 1 - постоянное, 2 - отложенное, можно сочетать |
getConnectionName() | привязка сущности к соединению | транзакции - в пределах своего соединения |
SqlHelper | диалект конкретной базы | делает код переносимым |
| Вертикальный шардинг | таблицы модуля на отдельный сервер | только веб-аналитика и поиск |
Частые ошибки
Двойные кавычки как строковый литерал. В PostgreSQL это идентификатор - запрос падает с сообщением о несуществующей колонке.
Обратные кавычки в запросах. MySQL-специфичный синтаксис, который ломает переносимость.
Явное квотирование идентификаторов. Делает их регистрозависимыми в PostgreSQL и ломает код, ожидающий имена колонок в верхнем регистре.
Неуникальные имена индексов. В MySQL допустимо, в PostgreSQL - конфликт, потому что имена глобальны в схеме.
Обратный слеш в литералах. Базы трактуют экранирование по-разному - значение всегда прогоняют через экранирование платформы.
MySQL-специфичные функции в запросах. Условные выражения, работа с датами, склейка строк, вставка с игнорированием и замена записи - всё это при переезде придётся переписывать вручную.
Частые вопросы
Что даёт перенос кеша в Redis или memcached?
Снимает с диска и с базы тысячи мелких операций. На нагруженном сайте файловый кеш сам становится узким местом: каталог разрастается, файловые операции конкурируют друг с другом. Redis дополнительно умеет хранить сессии и очереди задач, memcached - только кеш. Подключается всё через секцию конфигурации, лицензионных ограничений нет.
Насколько сложно перевести проект на PostgreSQL?
Сложность определяется тем, сколько в проекте прямого SQL. Код на ORM переносится без доработок - за диалект отвечает помощник SQL. А вот запросы с обратными кавычками, двойными кавычками вместо строк, специфичными функциями MySQL и явным квотированием идентификаторов придётся переписывать. Плюс организационный момент: PostgreSQL требует отдельной лицензии.
Можно ли распределить инфоблоки по нескольким серверам?
Нет. Платформа поддерживает только вертикальный шардинг и только для таблиц веб-аналитики и поиска - их выносят на отдельный сервер, логика приложения при этом не меняется. Для масштабирования основной базы используют репликацию с балансировкой чтения из модуля веб-кластера.
Зачем нужен HandlerSocket?
Это протокол прямого доступа к данным MySQL в обход разбора SQL - он ускоряет массовые операции чтения по ключу. Ниша узкая: только чтение и только простые обращения. На большинстве проектов вопрос закрывается кешем в памяти и правильными индексами, а HandlerSocket остаётся вариантом для специфичных нагрузок.
Связанные темы
- Веб-кластер - репликация и распределённый кеш
- Кеширование - что хранить в памяти
- D7 ORM - переносимые запросы
- Не создаётся резервная копия - дамп базы средствами сервера
- MySQL Query Error - пределы соединений и блокировки на практике
- Ошибки сервера и базы данных - разбор сбоев базы
- Раздел Производительность
- База данных в веб-окружении: запуск, настройки, доступ снаружи - база внутри веб-окружения
- Запросы к базе - поиск медленных запросов и индексы