Прерывание запросов: руководство по настройке SQL Block Rule и Workload Policy
Прерывание запросов — это механизм защиты, который предотвращает влияние длительных или ресурсоёмких запросов на стабильность кластера. Когда запрос превышает заданные ограничения по ресурсам или времени, механизм защиты автоматически завершает его, не позволяя одному запросу исчерпать системные ресурсы или замедлить выполнение других рабочих нагрузок.
Doris предоставляет два механизма прерывания, которые действуют на разных этапах жизненного цикла запроса:
| Критерий | SQL Block Rule (прерывание на этапе планирования) | Workload Policy (прерывание во время выполнения) |
|---|---|---|
| Этап срабатывания | Этап планирования запроса: перехват до начала выполнения | Этап выполнения запроса: прерывание во время работы |
| Основание для срабатывания | Оценочный объём сканирования, сопоставление с шаблонами SQL | Метрики в реальном времени: фактическое время выполнения, использование памяти, объём сканирования |
| Точность | Использует оценку стоимости, возможны ложные срабатывания | Использует мониторинг в реальном времени, более высокая точность |
| Сценарий использования | Блокировка известных опасных шаблонов SQL и полного сканирования таблиц | Прерывание выполняющихся запросов, которые превышают ожидаемые показатели |
| Поддерживаемые операторы | Любые операторы (DDL, DML) | select, insert into select, stream load, routine load |
SQL Block Rule
SQL Block Rule перехватывает операторы, соответствующие заданным шаблонам, на этапе планирования, не допуская их выполнения. Обычно этот механизм настраивают администраторы баз данных для предотвращения заведомо рискованных операций, таких как полное сканирование таблиц и вызовы опасных функций.
Свойства правила
Каждое правило определяется следующими свойствами, которые задают его поведение и область действия:
| Свойство | Описание | Значение |
|---|---|---|
sql | Регулярное выражение для сопоставления с текстом запроса | Строка с регулярным выражением Java |
sqlHash | Хеш-значение для сопоставления с запросом | Строка с хеш-значением SQL |
cardinality | Максимальное допустимое количество сканируемых строк | Положительное целое число |
partition_num | Максимальное допустимое количество сканируемых партиций | Положительное целое число |
tablet_num | Максимальное допустимое количество сканируемых tablet | Положительное целое число |
global | Является ли правило глобальным | "true" (глобальное) / "false" (действует только для пользователей, к которым привязано правило) |
enable | Включено ли правило | "true" / "false" |
Сценарии использования и примеры
Сценарий 1: ограничение количества сканируемых строк
Проблема: операции полного сканирования таблицы, такие как SELECT * FROM t, потребляют значительные ресурсы IO и CPU на BE.
Решение: задайте верхний предел количества строк, сканируемых в одной таблице. Запросы, превышающие этот порог, блокируются.
CREATE SQL_BLOCK_RULE rule_card
PROPERTIES
(
"cardinality" = "1000",
"global" = "true",
"enable" = "true"
);
Если при сканировании одной таблицы количество строк превышает 1000, запрос отклоняется.
Сценарий 2: ограничение количества сканируемых партиций
Проблема: сканирование слишком большого количества партиций значительно увеличивает потребление ресурсов CPU на BE. При запросах к внешним таблицам также возрастают накладные расходы на сетевое взаимодействие и получение метаданных. Обычно это связано с отсутствующими или неправильно заданными условиями фильтрации по партициям.
Решение: задайте максимальное количество партиций, которое может сканировать один запрос.
CREATE SQL_BLOCK_RULE rule_part_num
PROPERTIES
(
"partition_num" = "30",
"global" = "true",
"enable" = "true"
);
Если при сканировании одной таблицы количество партиций превышает 30, запрос отклоняется.
Сценарий 3: ограничение количества сканируемых tablet
Проблема: сканирование слишком большого количества tablet также значительно увеличивает потребление ресурсов CPU на BE.
Решение: задайте максимальное количество tablet, которое может сканировать один запрос.
CREATE SQL_BLOCK_RULE rule_tablet_num
PROPERTIES
(
"tablet_num" = "200",
"global" = "true",
"enable" = "true"
);
Если при сканировании одной таблицы количество tablet превышает 200, запрос отклоняется.
Сценарий 4: блокировка определённых шаблонов SQL
Проблема: некоторые шаблоны запросов, например вызовы определённых функций или выполнение опасных операций, могут приводить к чрезмерной вычислительной сложности или длительному планированию.
Решение: блокируйте такие запросы с помощью сопоставления с регулярными выражениями.
Пример 1: блокировка использования определённой функции
Следующее правило блокирует все запросы, содержащие функцию abs:
CREATE SQL_BLOCK_RULE rule_abs
PROPERTIES(
"sql"="(?i)abs\\s*\\(.+\\)",
"global"="true",
"enable"="true"
);
Разбор регулярного выражения:
(?i): сопоставление без учёта регистраabs: имя целевой функции\\s*: допускает любые пробельные символы между именем функции и открывающей скобкой\\(.+\\): соответствует аргументам функции
Пример 2: блокировка опасных операций
Аналогичным образом можно использовать регулярные выражения для блокировки set global (чтобы предотвратить непреднамеренное изменение переменных) или truncate table (чтобы предотвратить непреднамеренное удаление данных).
Регулярные выражения используют синтаксис Java. Подробности см. в документации Pattern.
Сценарий 5: настройка правил для определённых пользователей
Проблема: по умолчанию правила действуют глобально, но в некоторых случаях ограничение должно распространяться только на определённых пользователей.
Решение: создайте неглобальное правило и привяжите его к нужному пользователю.
-
При создании правила задайте для
globalзначение"false":CREATE SQL_BLOCK_RULE rule_001
PROPERTIES (
"sql"="select \\* from t",
"global" = "false",
"enable" = "true"
); -
Привяжите правило к нужному пользователю:
SET PROPERTY FOR 'root' 'SQL_block_rules' = 'rule_001'; -
Убедитесь, что правило действует:
MySQL root@127.0.0.1:test> select * from t;
(1105, 'errCode = 2, detailMessage = errCode = 2, detailMessage = SQL match regex SQL block rule: rule_001')
Управление несколькими правилами:
- Чтобы привязать к пользователю несколько правил, разделите их имена в списке запятыми, например
'rule_001,rule_002'. - Чтобы удалить все привязки правил к пользователю, задайте пустую строку в качестве списка правил, например
SET PROPERTY FOR 'root' 'SQL_block_rules' = '';.
Примечания
- Метод оценки: количество сканируемых строк, партиций и tablet оценивается на этапе планирования для наихудшего случая. Учитывается только отсечение партиций и tablet, остальные условия фильтрации не учитываются. Поэтому могут блокироваться и запросы, фактический объём сканирования которых меньше заданного значения.
- Влияние на производительность: сопоставление с регулярными выражениями требует значительных вычислительных ресурсов. Слишком большое количество правил с регулярными выражениями или их чрезмерная сложность создают значительную нагрузку на CPU FE, поэтому добавляйте их осмотрительно.
- Временное отключение правила: измените значение свойства
"enable"на"false", чтобы временно отключить правило, не удаляя его.
Workload Policy
Workload Policy отслеживает метрики в реальном времени во время выполнения запросов и применяет к запросам, превышающим ожидаемые показатели, такие действия, как прерывание или изменение переменных. В отличие от статической оценки SQL Block Rule на этапе планирования, Workload Policy принимает решения на основе фактических данных выполнения и обеспечивает более высокую точность.
Workload Policy поддерживается начиная с Doris 2.1. Поддержка для каждого типа рабочей нагрузки указана ниже:
| Тип рабочей нагрузки | Поддержка |
|---|---|
| select | Да |
| insert into select | Да |
| insert into values | Нет |
| stream load | Да |
| routine load | Да |
| backup | Нет |
| compaction | Нет |
Создание и настройка
Для создания политики используйте команду CREATE WORKLOAD POLICY. Требуется привилегия admin_priv.
Базовый синтаксис:
CREATE WORKLOAD POLICY <policy_name>
CONDITIONS(<condition_expr>)
ACTIONS(<action_expr>)
PROPERTIES('<key>'='<value>');
В следующем примере создаётся политика, которая отменяет запросы, выполняющиеся дольше 1000 мс:
CREATE WORKLOAD POLICY test_cancel_policy
CONDITIONS(query_time > 1000)
ACTIONS(cancel_query)
PROPERTIES('enabled'='true');
Условия срабатывания
Условия определяют, когда срабатывает политика. Несколько условий разделяются запятыми (,), что соответствует логическому AND.
| Условие | Описание |
|---|---|
username | Имя пользователя, передаваемое с запросом. Начиная с Doris 4.1.3, его можно сочетать с метриками времени выполнения на BE, такими как query_time, be_scan_rows, be_scan_bytes и query_be_memory_bytes, для срабатывания cancel_query. Это условие поддерживает только оператор равенства (=), а имя пользователя не может быть пустым |
be_scan_rows | Количество строк, сканируемых запросом SQL в пределах одного процесса BE. При параллельном выполнении значения суммируются |
be_scan_bytes | Количество байтов, сканируемых запросом SQL в пределах одного процесса BE. При параллельном выполнении значения суммируются (единица измерения: байты) |
query_time | Время выполнения запроса SQL в одном процессе BE (единица измерения: миллисекунды) |
query_be_memory_bytes | Объём памяти, используемой запросом SQL в пределах одного процесса BE. При параллельном выполнении значения суммируются (единица измерения: байты) |
Действия
Действия определяют, что следует делать при выполнении условий. В настоящее время в политике можно задать только одно действие.
| Действие | Описание |
|---|---|
cancel_query | Отменить запрос |
Свойства политики
| Свойство | Описание | Значение по умолчанию |
|---|---|---|
enabled | Включена ли политика. Значение: true или false | true |
priority | Приоритет в диапазоне от 0 до 100. Чем больше значение, тем выше приоритет. Если подходят несколько политик, применяется только политика с наивысшим приоритетом | 0 |
workload_group | Имя привязанной Workload Group. Если оно указано, политика применяется только к запросам в этой Workload Group. При пустом значении политика применяется ко всем запросам | Пустое значение (глобальная область действия) |
Привязка к Workload Group
Чтобы ограничить действие политики определённой Workload Group, привяжите её с помощью свойства workload_group:
CREATE WORKLOAD POLICY test_cancel_big_query
CONDITIONS(query_time > 1000)
ACTIONS(cancel_query)
PROPERTIES('workload_group'='normal');
Приведённая выше форма 'workload_group'='normal' допустима только в необлачном режиме (с совмещёнными хранением и вычислениями). В облачном режиме (с разделёнными хранением и вычислениями) требуется полная форма <compute_group>.<workload_group>, например 'workload_group'='compute_group_a.normal'; иначе оператор завершится с ошибкой: workload_group must be '<compute_group>.<workload_group>' in cloud mode. Подробности см. в разделе CREATE WORKLOAD POLICY.
Примеры
Пример 1: прерывание длительных запросов
Следующий журнал аудита показывает, что выполнение запроса SQL обычно занимает 4.5 секунды:
MySQL [hits]> SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\\.)?([^/]+)/.*$', '\\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;
+-----------------------------------------------------------------------+------------------+----------+---------------------------------------------------------------------------------------------------------------------+
| k | l | c | min(Referer) |
+-----------------------------------------------------------------------+------------------+----------+---------------------------------------------------------------------------------------------------------------------+
| 1 | 85.4611926713085 | 67259319 | http://%26ad%3D1%25EA%25D0%26utm_source=web&cd=19590&input_onlist/би-2 место будущей кондицин |
| http:%2F%2Fwwww.regnancies/search&evL8gE&where=all&filmId=bEmYZc_WTDE | 69 | 207347 | http:%2F%2Fwwww.regnancies/search&evL8gE&where=all&filmId=bEmYZc_WTDE |
| http://новострашная | 31 | 740277 | http://новострашная |
| http://loveche.html?ctid | 24 | 144901 | http://loveche.html?ctid |
| http://rukodeliveresult | 23 | 226135 | http://rukodeliveresult |
| http://holodilnik.ru | 20 | 133893 | http://holodilnik.ru |
| http://smeshariki.ru | 20 | 210736 | http://smeshariki.ru |
| http:%2F%2Fviewtopic | 20 | 391115 | http:%2F%2Fviewtopic |
| http:%2F%2Fwwww.ukr | 19 | 655178 | http:%2F%2Fwwww.ukr |
| http:%2F%2FviewType | 19 | 148907 | http:%2F%2FviewType |
| http://state=2008 | 17 | 139630 | http://state=2008 |
+-----------------------------------------------------------------------+------------------+----------+---------------------------------------------------------------------------------------------------------------------+
11 rows in set (4.50 sec)
Создайте политику, которая отменяет любой запрос, выполняющийся дольше 3 секунд:
CREATE WORKLOAD POLICY test_cancel_3s_query
CONDITIONS(query_time > 3000)
ACTIONS(cancel_query);
Выполните тот же запрос SQL ещё раз: он будет прерван.
MySQL [hits]> SELECT REGEXP_REPLACE(Referer, '^https?://(?:www\\.)?([^/]+)/.*$', '\\1') AS k, AVG(length(Referer)) AS l, COUNT(*) AS c, MIN(Referer) FROM hits WHERE Referer <> '' GROUP BY k HAVING COUNT(*) > 100000 ORDER BY l DESC LIMIT 25;
ERROR 1105 (HY000): errCode = 2, detailMessage = (127.0.0.1)[CANCELLED]query cancelled by workload policy,id:12345
Пример 2: прерывание тяжёлых запросов определённого пользователя во время выполнения
Начиная с Doris 4.1.3, можно сочетать username с метриками времени выполнения на BE, чтобы отменять только запросы определённого пользователя. Следующая политика отменяет запросы пользователя test_user, если время их выполнения на одном BE превышает 3000 мс:
CREATE WORKLOAD POLICY cancel_user_long_query
CONDITIONS(username='test_user', query_time > 3000)
ACTIONS(cancel_query);
Аналогичным образом username можно сочетать с be_scan_rows, be_scan_bytes или query_be_memory_bytes, чтобы ограничить объём сканирования или использование памяти BE для определённого пользователя.
Примечания
- Задержка из-за асинхронного выполнения: политики проверяются асинхронным потоком каждые 500 мс, поэтому они применяются с некоторой задержкой. Очень короткие запросы могут завершиться до проверки и избежать применения политики.
- Механизм приоритетов: запрос может соответствовать нескольким политикам, но применяется только политика с наивысшим приоритетом (наибольшим значением
priority). - Ограничение на изменение: в настоящее время нельзя напрямую изменить действие и условие существующей политики. Удалите политику и создайте её заново.