Записи, вставленные в таблицу QueryRunner, представляют собой запросы, которые выполняет движок.
Движок можно использовать для асинхронного выполнения запросов, батчевого выполнения сгенерированных запросов,
отправки запросов в удаленные кластеры, запуска бенчмарков, фаззинга и тестирования с теневым трафиком.
Создание таблицы
CREATE TABLE runner
(
query String,
database String,
settings Map(LowCardinality(String), String)
)
ENGINE = QueryRunner
SETTINGS
cluster = 'cluster_name',
shard = '1',
mode = 'asynchronous',
threads = 4,
max_queue_size = 1000
[DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER | NONE }];Таблица должна быть создана с подмножеством допустимых столбцов: query, database, settings.
Столбец query обязателен, остальные столбцы — необязательны.
| Столбец | Type | Значение |
|---|---|---|
query |
String |
Запрос, который нужно выполнить. |
database |
String |
База данных по умолчанию для запроса. Если значение пустое, используется база данных сервера по умолчанию. |
settings |
Map(String, String) |
Настройки, применяемые к запросу. |
Настройки движка
| Setting | Default | Meaning |
|---|---|---|
cluster |
'' |
Имя кластера, в который отправляются запросы. Если значение пустое, запросы выполняются локально. |
shard |
'1' |
Индекс сегмента кластера, начиная с 1, в который отправляются запросы, или 'random' для выбора случайного сегмента для каждого запроса, или 'all', чтобы выполнять каждый запрос на каждом сегменте. Требует настройки cluster. |
mode |
'asynchronous' |
В режиме synchronous INSERT возвращает управление после завершения всех запросов из вставленного батча. В режиме asynchronous INSERT возвращает управление, как только запросы поставлены в очередь. |
threads |
4 |
Количество фоновых потоков, выполняющих запросы. |
max_queue_size |
1000 |
Максимальное количество запросов в очереди. Когда очередь заполнена, новые запросы отбрасываются, а ошибка записывается в журнал. |
Подробности
Таблица допускает только запросы INSERT.
Запросы выполняются в режиме "fire and forget": в случае исключения повторных попыток не выполняется,
а результаты запросов SELECT отбрасываются (единственный способ сохранить результаты — INSERT SELECT).
Успешность каждого запроса можно проверить в таблице system.query_log, где запросы, инициированные
этим движком, помечаются как is_internal = 1 на инициирующем сервере.
Поставленные в очередь запросы хранятся в памяти и не сохраняются после перезапуска сервера. При остановке сервера
(или DROP/DETACH таблицы) запросы, которые еще не начали выполняться, отбрасываются. Из
запросов, которые уже выполняются, отправленные в кластер отменяются, а выполняющиеся
локально продолжают выполняться до завершения.
Если выполняемый запрос сам является INSERT, его данные должны быть указаны прямо в нем — INSERT ... VALUES (...),
INSERT ... SELECT ... или INSERT ... FORMAT ... с данными в тексте запроса. INSERT, который
ожидает данные из отдельного потока, не поддерживается.
Локальный режим и безопасность SQL
Без настройки cluster запросы выполняются на локальном сервере.
Пользователь, от имени которого они выполняются, определяется конструкцией безопасность SQL:
INVOKER(по умолчанию): запросы выполняются от имени пользователя, который выполнил INSERT.DEFINER: запросы выполняются от имени указанного пользователяDEFINER. Поскольку такие запросы могут быть произвольными, предоставлениеINSERTна такую таблицу делегирует все привилегии пользователяDEFINER.NONE: запросы выполняются с полным доступом, без пользователя. При создании таблицы требуется grantALLOW_SQL_SECURITY_NONE.
Режим кластера
Когда указана настройка cluster, запросы отправляются в указанный кластер.
Целевой сегмент выбирается с помощью shard: это может быть фиксированный индекс с нумерацией с 1 (по умолчанию '1'), 'random' для выбора
случайного сегмента для каждого запроса или 'all' для выполнения каждого запроса на каждом сегменте кластера. Реплика внутри
сегмента выбирается в соответствии с настройкой load_balancing сервера.
Столбец database задаёт базу данных по умолчанию для соединения с удалённым сервером. Поскольку
база данных по умолчанию задаётся один раз для каждого соединения, каждое отдельное значение database использует собственный
пул соединений, который создаётся при первом использовании и затем повторно используется в течение всего времени жизни таблицы.
DEFINER и безопасность SQL действуют только в локальном режиме, а их сочетание с
настройкой cluster приводит к ошибке. На удалённых серверах запросы проходят аутентификацию с использованием
учётных данных из конфигурации кластера и выполняются как обычные исходные запросы: они записываются в
system.query_log с is_initial_query = 1 и собственным query_id (не связанным с INSERT, который
их создал). На инициирующем сервере отправленные запросы записываются в system.query_log
с is_internal = 1.
Поскольку движок отбрасывает результаты запросов, он всегда выполняет отправленные запросы с
discard_query_data = 1, поэтому данные результата SELECT-запросов не передаются по сети
(это переопределяет любое значение discard_query_data, заданное в столбце settings).
Ожидание завершения запросов
В асинхронном режиме можно использовать следующий запрос, чтобы блокировать выполнение до тех пор, пока не завершатся все запросы, к этому моменту отправленные в таблицу:
SYSTEM WAIT QUERY RUNNER runner;Пример
Повторное выполнение последних запросов SELECT из журнала запросов:
INSERT INTO runner (query, database, settings)
SELECT query, current_database, Settings
FROM system.query_log
WHERE type = 'QueryFinish' AND is_initial_query AND NOT is_internal AND query_kind = 'Select'
AND event_time > now() - INTERVAL 1 HOUR;