Skip to main content

mysql

MySQL/MariaDB: удалённая база, не блокирующая кадр. Для той базы, которая не лежит рядом с сервером — сайт, панель, общий для нескольких серверов проекта аккаунт. Для локальных данных проще db: он синхронный и не тянет за собой внешний процесс.
Тот же приём, что и http: запрос уходит на рабочий поток, ответ возвращается в игровой — тем же проходом, которым тикают таймеры и ходят HTTP-ответы. Ни одна строчка плагина не касается сокета. Вызов :query/:exec ничего не ждёт: он возвращается сразу с id, кадр идёт дальше, коллбэк приходит когда придёт. Опциональные хелперы find / create / update / delete собирают безопасный SQL сами: имена таблиц и колонок — только [A-Za-z0-9_], значения идут через ?. Для JOIN, подзапросов и сложного WHERE остаётся сырой :query / :exec. Миграции схемы — conn:migrate. mysql.connect тоже не ждёт: соединение открывается лениво, на рабочем потоке, при первом запросе — сам вызов connect кадр не блокирует и связку не проверяет.

Значения через ?

Как в db, но экранирование делает рабочий поток на живом соединении, а не драйвер напрямую:
Не склеивай запрос из данных игрока — так же, как и с db: через ? значение попадёт в базу строкой, чем бы ни было, в склейке — станет частью запроса.

Транспорт

Клиентская библиотека MySQL — не часть модуля: она открывается при первом запросе, как libcurl у http, а не линкуется в сборку. Сервер без клиентской библиотеки нормально загрузит модуль: res.error скажет об этом при первом обращении к соединению, а не при старте.

Объект ответа

Коллбэк получает одну таблицу. Строка в res.rows — таблица с ключами по именам колонок; NULL приходит как отсутствующий ключ, ровно как в db. Тип колонки в SQL решает, придёт значение числом или строкой: Даты и время остаются строкой не просто так: у них нет единого числового представления, которое не потребовало бы parse на другом конце — так же, как в исходном TEXT-протоколе MySQL, откуда и приходит сырое значение.

Одно соединение — одна очередь

Два запроса на разных соединениях выполняются параллельно (рабочих потоков несколько). Два запроса на одном и том же соединении всегда идут по очереди — MySQL-соединение нельзя использовать из двух мест одновременно, поэтому нужен параллелизм — открывай второе соединение, а не жди на одном.

Обрыв связи

Ошибка запроса закрывает соединение изнутри; следующий вызов :query/:exec/:find/:create/:update/:delete/:migrate на этом же объекте переподключается заново сам, без явного :connect(). Платится это одним лишним переподключением и на обычную опечатку в SQL — дёшево по сравнению с тем, чтобы намертво зависнуть на упавшем сайте.

Перезагрузка и выгрузка

Как и http: запросы, оставшиеся на проводе, переживают lua_reload и выгрузку плагина, но их коллбэки не выполняются — ответ выбрасывается. Перезагрузка не ждёт незавершённые запросы. Соединения при этом не рвутся: сокет остаётся открытым и простаивает до остановки сервера, чтобы не ждать рабочий поток на середине запроса.

Открытие

Объект соединения