Database API

Техническая архитектура и базовые протоколы
Database API в экосистеме SourceMod представляет собой абстрактный слой, обеспечивающий унифицированный доступ к реляционным СУБД. Его ядро компилируется в двоичный модуль, который взаимодействует с внешними библиотеками, такими как libmysqlclient или sqlite3. API использует драйверную модель, где каждый драйвер реализует стандартный интерфейс для обработки соединений, пулов и транзакций. Это позволяет подключаться к MySQL, PostgreSQL и SQLite через идентичный набор нативных функций, минимизируя код плагина. Архитектура строго разделяет логику установки соединения и выполнения запросов, что критично для стабильности сервера.
Точная процедура настройки драйверов и подключения
Перед использованием API необходимо обеспечить наличие и корректную настройку драйверов на уровне SourceMod. Для MySQL требуется файл libmysqlclient, который размещается в папке extensions. Драйвер SQLite поставляется в составе базовой сборки SourceMod. Основная конфигурация подключений хранится в файле databases.cfg в формате KeyValues. В этом файле вы определяете именованные профили подключений с конкретными параметрами. Каждый профиль должен содержать точные технические параметры, включая таймауты и размер пула. Без корректного конфигурационного файла плагин не сможет установить связь с базой данных.
- Драйвер MySQL: Скачайте бинарный файл с официального репозитория SourceMod, соответствующий вашей ОС (Linux: .so, Windows: .dll). Поместите его в директорию `addons/sourcemod/extensions`. Убедитесь, что версия библиотеки совместима с версией вашего сервера и СУБД.
- Драйвер SQLite: Включён по умолчанию, не требует дополнительных загрузок. Для активации укажите `driver` = `sqlite` в конфигурации. База данных будет создана в виде файла на диске сервера, путь указывается относительно корневой папки игры.
- Параметры подключения для MySQL: Обязательные ключи: `host` (IP или домен), `database` (имя БД), `user` и `pass`. Дополнительные: `port` (по умолчанию 3306), `timeout` (значение в секундах, рекомендуется 30), `charset` (например, utf8mb4).
- Параметры подключения для SQLite: Ключ `database` должен содержать относительный путь к файлу .sqlite, например `csgo_data.sqlite`. Драйвер автоматически создаст файл при первом подключении, если его не существует.
- Определение размера пула: Используйте параметр `max_connections` или `max_timeout`. Для типичного игрового сервера с 64 слотами достаточно пула из 3-5 соединений. Превышение этого значения создаёт избыточную нагрузку на СУБД.
После редактирования файла databases.cfg перезапуск сервера не обязателен. Конфигурация перечитывается при каждом запросе нового соединения через API. Однако изменения в самих драйверах (замена файлов .dll/.so) требуют полной перезагрузки серверного процесса.
Методы написания и оптимизации SQL-запросов
Эффективность плагина напрямую зависит от качества формируемых SQL-запросов. Database API предоставляет два основных метода: `SQL_Query` для операций чтения (SELECT) и `SQL_Execute` или `SQL_Query` для операций изменения (INSERT, UPDATE, DELETE). Все строки запросов должны быть экранированы через `SQL_EscapeString` для предотвращения инъекций. Для параметризованных запросов используйте `SQL_BindParamInt`, `SQL_BindParamFloat`, `SQL_BindParamString` — это предпочтительный метод, повышающий безопасность и производительность. Избегайте составления запросов через конкатенацию строк с пользовательским вводом.
Критически важна оптимизация запросов, выполняемых в игровых тиках, таких как `OnPlayerDeath` или `OnRoundStart`. Создавайте индексы в таблицах базы данных на часто запрашиваемых столбцах, например, `steamid`, `timestamp`. Для сложных операций агрегации (подсчёт статистики) используйте предварительно рассчитанные таблицы или кэширование результатов в памяти плагина. Лимитируйте выборки с помощью `LIMIT` и выбирайте только необходимые столбцы, а не `SELECT *`.
Управление асинхронными операциями и потоками
Синхронные запросы блокируют основной поток сервера, что приводит к "лагам" при высокой нагрузке. Database API реализует асинхронную модель через обратные вызовы (callbacks). Используйте функции `SQL_TQuery` для неблокирующего выполнения. Эта функция принимает хендл базы данных, строку запроса, ссылку на функцию-обработчик и произвольные данные (DataPack или значение). Сервер продолжает обрабатывать игровые события, пока запрос выполняется в отдельном потоке пула. По завершении запроса вызывается указанная функция, где вы можете обработать результат через `SQL_GetRowCount` и `SQL_FetchRow`.
- Структура асинхронного вызова: `SQL_TQuery(dbHandle, callbackFunction, queryString, dataPack);`. Параметр `dbHandle` получается через `SQL_Connect`. `callbackFunction` должна иметь сигнатуру `public void Callback(Handle owner, Handle hndl, const char[] error, any data)`.
- Обработка ошибок в коллбэке: Первым делом проверьте, не пуста ли строка `error`. Если она содержит текст, запрос завершился неудачей — залогируйте ошибку через `LogError` и освободите ресурсы (например, `CloseHandle(data)`).
- Использование DataPack для передачи контекста: Упакуйте необходимые данные (SteamID, время события) перед запросом с помощью `CreateDataPack()`, `WritePackCell()`, `WritePackString()`. В коллбэке распакуйте данные для корректной обработки результата.
- Ограничение пула потоков: SourceMod использует фиксированный пул потоков для всех расширений. Одновременное выполнение десятков тяжелых асинхронных запросов может исчерпать пул. Контролируйте количество активных запросов, особенно в событиях с массовым срабатыванием.
- Приоритизация запросов: Критичные для геймплея запросы (проверка бан-листа) выполняйте синхронно или с высоким приоритетом. Статистические или логирующие запросы отправляйте асинхронно с возможностью отложенного выполнения.
Асинхронная модель требует тщательного управления памятью. Все хендлы, созданные в ходе запроса (например, `DBResultSet`), должны быть закрыты в коллбэке с помощью `CloseHandle()`. Утечка хендлов приводит к постепенному увеличению потребления памяти и нестабильности сервера. Используйте встроенные отладчики SourceMod для мониторинга количества открытых хендлов.
Стандарты безопасности и предотвращение уязвимостей
Безопасность взаимодействия с базой данных строится на двух принципах: валидация входных данных и параметризация запросов. Любые данные, полученные от клиента (никнейм, сообщение в чате), должны рассматриваться как потенциально опасные. Перед использованием в запросе их необходимо обработать функцией `SQL_EscapeString`, которая экранирует специальные символы. Однако более надежным методом является использование привязки параметров через `SQL_BindParam`. Этот метод передаёт данные отдельно от текста запроса, что полностью исключает возможность SQL-инъекции на уровне драйвера.
Настройте права доступа пользователя базы данных (для MySQL/PostgreSQL) по принципу минимальных привилегий. Учётная запись, которую использует игровой сервер, не должна иметь прав на DROP, GRANT или доступ к другим базам. Ограничьте её права только необходимыми операциями SELECT, INSERT, UPDATE, DELETE на конкретных таблицах. Регулярно обновляйте драйверы и библиотеки СУБД для устранения известных уязвимостей. Ведение детального лога всех ошибок базы данных в отдельный файл поможет вовремя обнаружить попытки атак или сбои в работе.
Мониторинг производительности и отладка запросов
Производительность Database API мониторится через комбинацию инструментов SourceMod и внешних средств СУБД. Включите детальное логирование запросов в конфигурации SourceMod, добавив `log_queries 1` в `sourcemod.cfg`. Это заставит движок записывать все выполняемые запросы и их время выполнения в файл `logs/sql.log`. Анализируйте этот лог на предмет медленных запросов, время выполнения которых превышает 100 миллисекунд. Для MySQL используйте встроенный slow query log, настроив параметр `long_query_time`. Профилируйте проблемные запросы с помощью `EXPLAIN` для выявления отсутствующих индексов или полных сканирований таблиц.
При отладке используйте встроенные функции SourceMod для проверки состояния соединения, такие как `SQL_IsSameConnection` или `SQL_CheckConfig`. Для симуляции нагрузки и проверки стабильности создайте тестовый плагин, который генерирует массовые параллельные запросы. Контролируйте использование оперативной памяти серверным процессом во время такой нагрузки. Убедитесь, что конфигурация пула соединений в `databases.cfg` соответствует реальной нагрузке, и при необходимости откорректируйте параметры `max_connections` и `timeout`.
Добавлено: 21.04.2026
