Spec-Zone.ru › MySQL 5.7

5.5.4.2 Использование плагина Rewriter Query Rewrite

Чтобы включить или отключить плагин, включите или отключите системную переменную rewriter_enabled. По умолчанию, плагин Rewriter включён при его установке (см. Раздел 5.5.4.1, «Установка или удаление плагина Rewriter Query Rewrite»). Чтобы явно установить начальное состояние плагина, можно задать переменную при запуске сервера. Например, чтобы включить плагин в файле опций, используйте эти строки:

[mysqld]
rewriter_enabled=ON

Также можно включить или отключить плагин во время выполнения:

SET GLOBAL rewriter_enabled = ON;
SET GLOBAL rewriter_enabled = OFF;

Предполагая, что плагин Rewriter включён, он анализирует и, возможно, изменяет каждый полученный сервером оператор SELECT. Плагин определяет, нужно ли переписывать операторы, основываясь на кэше правил переписывания в оперативной памяти, загружаемых из таблицы rewrite_rules в базе данных query_rewrite.

  • Добавление правил переписывания

  • Как работает сопоставление операторов

  • Переписывание подготовленных операторов

  • Справочная информация о работе плагина Rewriter

  • Использование наборов символов плагином Rewriter

Добавление правил переписывания

Чтобы добавить правила для плагина Rewriter, добавьте строки в таблицу rewrite_rules, а затем вызовите хранимую процедуру flush_rewrite_rules(), чтобы загрузить правила из таблицы в плагин. Следующий пример создаёт простое правило для сопоставления операторов, выбирающих одно литеральное значение:

INSERT INTO query_rewrite.rewrite_rules (pattern, replacement)
VALUES('SELECT ?', 'SELECT ? + 1');

Содержимое получившейся таблицы выглядит так:

mysql> SELECT * FROM query_rewrite.rewrite_rules\G
*************************** 1. row ***************************
                id: 1
           pattern: SELECT ?
  pattern_database: NULL
       replacement: SELECT ? + 1
           enabled: YES
           message: NULL
    pattern_digest: NULL
normalized_pattern: NULL

Правило определяет шаблон для операторов SELECT, которые нужно сопоставить, и шаблон для переписывания сопоставленных операторов. Однако, добавления правила в таблицу rewrite_rules недостаточно, чтобы плагин Rewriter использовал это правило. Нужно вызвать flush_rewrite_rules(), чтобы загрузить содержимое таблицы в кэш плагина в оперативной памяти:

mysql> CALL query_rewrite.flush_rewrite_rules();
Подсказка

Если ваши правила переписывания работают некорректно, убедитесь, что вы перезагрузили таблицу правил, вызвав flush_rewrite_rules().

Когда плагин читает каждое правило из таблицы правил, он вычисляет нормализованную (digest оператора) форму из шаблона и значение хеша digest и использует их для обновления столбцов normalized_pattern и pattern_digest:

mysql> SELECT * FROM query_rewrite.rewrite_rules\G
*************************** 1. row ***************************
                id: 1
           pattern: SELECT ?
  pattern_database: NULL
       replacement: SELECT ? + 1
           enabled: YES
           message: NULL
    pattern_digest: 46b876e64cd5c41009d91c754921f1d4
normalized_pattern: select ?

Сведения о разборе операторов, нормализованных операторах и значениях хешей digest см. в Разделе 25.10, «Performance Schema Statement Digests».

Если правило не может быть загружено из-за ошибки, вызов flush_rewrite_rules() генерирует ошибку:

mysql> CALL query_rewrite.flush_rewrite_rules();
ERROR 1644 (45000): Loading of some rule(s) failed.

В этом случае плагин записывает сообщение об ошибке в столбец message строки правила, чтобы сообщить о проблеме. Проверьте таблицу rewrite_rules на наличие строк с не-NULL значениями столбца message, чтобы увидеть, какие проблемы существуют.

Шаблоны используют ту же синтаксическую конструкцию, что и подготовленные операторы (см. Раздел 13.5.1, «PREPARE Statement»). В шаблоне правила символы ? выступают в качестве маркеров параметров, которые соответствуют значениям данных. Символы ? не должны быть заключены в кавычки. Маркеры параметров могут использоваться только там, где должны быть значения данных, и они не могут использоваться для SQL-ключевых слов, идентификаторов, функций и т. д. Плагин анализирует оператор, чтобы определить литеральные значения (как определено в Разделе 9.1, «Литеральные значения»), поэтому вы можете разместить маркер параметра вместо любого литерального значения.

Как и шаблон, замена может содержать ? символы. Для оператора, который соответствует шаблону правила, плагин переписывает его, заменяя ? маркеры параметров в замене значениями данных, соответствующими этим маркерам в шаблоне. Результатом является полная строка оператора. Плагин просит сервер проанализировать его и возвращает результат серверу как представление переписанного оператора.

После добавления и загрузки правила проверьте, происходит ли переписывание в соответствии с тем, соответствуют ли операторы шаблону правила:

mysql> SELECT PI();
+----------+
| PI()     |
+----------+
| 3.141593 |
+----------+
1 row in set (0.01 sec)

mysql> SELECT 10;
+--------+
| 10 + 1 |
+--------+
|     11 |
+--------+
1 row in set, 1 warning (0.00 sec)

Переписывание не происходит для первого SELECT оператора, но происходит для второго. Второй оператор демонстрирует, что при переписывании оператора плагином Rewriter генерируется сообщение об ошибке. Чтобы просмотреть сообщение, используйте SHOW WARNINGS:

mysql> SHOW WARNINGS\G
*************************** 1. row ***************************
  Level: Note
   Code: 1105
Message: Query 'SELECT 10' rewritten to 'SELECT 10 + 1' by a query rewrite plugin

Чтобы включить или отключить существующее правило, измените его столбец enabled и перезагрузите таблицу в плагин. Чтобы отключить правило 1:

UPDATE query_rewrite.rewrite_rules SET enabled = 'NO' WHERE id = 1;
CALL query_rewrite.flush_rewrite_rules();

Это позволяет вам деактивировать правило, не удаляя его из таблицы.

Чтобы повторно включить правило 1:

UPDATE query_rewrite.rewrite_rules SET enabled = 'YES' WHERE id = 1;
CALL query_rewrite.flush_rewrite_rules();

Таблица rewrite_rules содержит столбец pattern_database, который Rewriter использует для сопоставления имён таблиц, которые не квалифицированы с именем базы данных:

  • Квалифицированные имена таблиц в операторах соответствуют квалифицированным именам в шаблоне, если соответствующие имена базы данных и таблиц идентичны.

  • Неквалифицированные имена таблиц в операторах соответствуют неквалифицированным именам в шаблоне только в том случае, если база данных по умолчанию совпадает с pattern_database и имена таблиц идентичны.

Предположим, что у таблицы с именем appdb.users есть столбец с именем id, и ожидается, что приложения будут выбирать строки из таблицы с помощью запроса одного из этих форматов, где второй можно использовать, когда appdb является базой данных по умолчанию:

SELECT * FROM users WHERE appdb.id = id_value;
SELECT * FROM users WHERE id = id_value;

Предположим также, что столбец id переименован в user_id (возможно, таблица должна быть изменена для добавления другого типа идентификатора, и необходимо более конкретно указать, какой тип идентификатора представляет столбец id).

Изменение означает, что приложения должны ссылаться на user_id вместо id в предложении WHERE, но старые приложения, которые нельзя обновить, больше не работают должным образом. Плагин Rewriter может решить эту проблему, сопоставляя и переписывая проблемные операторы. Чтобы сопоставить оператор SELECT * FROM appdb.users WHERE id = value и переписать его как SELECT * FROM appdb.users WHERE user_id = value, можно вставить строку, представляющую правило замены, в таблицу правил переписывания. Если вы также хотите сопоставить этот SELECT, используя неквалифицированное имя таблицы, необходимо также добавить явное правило. Используя ? в качестве заменителя значения, два необходимых оператора INSERT выглядят так:

INSERT INTO query_rewrite.rewrite_rules
    (pattern, replacement) VALUES(
    'SELECT * FROM appdb.users WHERE id = ?',
    'SELECT * FROM appdb.users WHERE user_id = ?'
    );
INSERT INTO query_rewrite.rewrite_rules
    (pattern, replacement, pattern_database) VALUES(
    'SELECT * FROM users WHERE id = ?',
    'SELECT * FROM users WHERE user_id = ?',
    'appdb'
    );

После добавления двух новых правил выполните следующий оператор, чтобы они вступили в силу:

CALL query_rewrite.flush_rewrite_rules();

Rewriter использует первое правило для сопоставления операторов, использующих квалифицированное имя таблицы, и второе — для сопоставления операторов, использующих неквалифицированное имя. Второе правило работает только тогда, когда appdb является базой данных по умолчанию.

Как работает сопоставление инструкций

Плагин Rewriter использует дайджесты инструкций и значения хешей дайджестов для сопоставления входящих инструкций с правилами переписывания в несколько этапов. Переменная системы max_digest_length определяет размер буфера, используемого для вычисления дайджестов инструкций. Более высокие значения позволяют вычислять дайджесты, которые различают более длинные инструкции. Более низкие значения используют меньше памяти, но увеличивают вероятность совпадения дайджестов для более длинных инструкций.

Плагин сопоставляет каждую инструкцию с правилами переписывания следующим образом:

  1. Вычислить значение хеша дайджеста инструкции и сравнить его со значениями хеша дайджестов правил. Это может привести к ложноположительным результатам, но служит быстрым тестом отклонения.

  2. Если значение хеша дайджеста инструкции совпадает с каким-либо значением хеша дайджеста шаблона, сопоставить нормализованную форму (дайджеста инструкции) инструкции с нормализованной формой соответствующих шаблонов правил.

  3. Если нормализованная инструкция соответствует правилу, сравнить значения литералов в инструкции и шаблоне. Символ ? в шаблоне соответствует любому значению литерала в инструкции. Если инструкция подготавливает инструкцию SELECT, символ ? в шаблоне также соответствует символу ? в инструкции. В противном случае соответствующие литералы должны быть одинаковыми.

Если нескольким правилам соответствует инструкция, плагин не определяет, какое из них использовать для переписывания инструкции.

Если шаблон содержит больше маркеров, чем замена, плагин отбрасывает избыточные значения данных. Если шаблон содержит меньше маркеров, чем замена, это ошибка. Плагин замечает это при загрузке таблицы правил, записывает сообщение об ошибке в столбец message строки правила, чтобы сообщить о проблеме, и устанавливает переменную состояния Rewriter_reload_error в значение ON.

Переписывание подготовленных инструкций

Подготовленные инструкции переписываются во время анализа (то есть, когда они готовятся), а не во время последующего выполнения.

Подготовленные инструкции отличаются от неподготовленных тем, что могут содержать символы ? в качестве маркеров параметров. Для сопоставления ? в подготовленной инструкции, шаблон Rewriter должен содержать ? в том же месте. Предположим, что правило переписывания имеет такой шаблон:

SELECT ?, 3

В следующей таблице показаны несколько подготовленных SELECT инструкций и соответствуют ли они шаблону правила.

Подготовленная инструкция Соответствует ли шаблон инструкции
PREPARE s AS 'SELECT 3, 3' Да
PREPARE s AS 'SELECT ?, 3' Да
PREPARE s AS 'SELECT 3, ?' Нет
PREPARE s AS 'SELECT ?, ?' Нет
Операционная информация плагина Rewriter

Плагин Rewriter предоставляет информацию о своей работе с помощью нескольких переменных состояния:

mysql> SHOW GLOBAL STATUS LIKE 'Rewriter%';
+-----------------------------------+-------+
| Variable_name                     | Value |
+-----------------------------------+-------+
| Rewriter_number_loaded_rules      | 1     |
| Rewriter_number_reloads           | 5     |
| Rewriter_number_rewritten_queries | 1     |
| Rewriter_reload_error             | ON    |
+-----------------------------------+-------+

Описание этих переменных см. в Раздел 5.5.4.3.4, «Переменные состояния плагина Rewriter Query Rewrite».

При загрузке таблицы правил с помощью вызова хранимой процедуры flush_rewrite_rules(), если возникнет ошибка для какого-либо правила, инструкция CALL вызовет ошибку, и плагин установит переменную состояния Rewriter_reload_error в значение ON:

mysql> CALL query_rewrite.flush_rewrite_rules();
ERROR 1644 (45000): Loading of some rule(s) failed.

mysql> SHOW GLOBAL STATUS LIKE 'Rewriter_reload_error';
+-----------------------+-------+
| Variable_name         | Value |
+-----------------------+-------+
| Rewriter_reload_error | ON    |
+-----------------------+-------+

В этом случае проверьте таблицу rewrite_rules на наличие строк со значениями столбца message, отличными от NULL, чтобы увидеть, какие проблемы существуют.

Использование наборов символов плагином Rewriter

При загрузке таблицы rewrite_rules в плагин Rewriter, плагин интерпретирует инструкции, используя текущее глобальное значение переменной системы character_set_client. Если глобальное значение character_set_client изменяется впоследствии, таблицу правил необходимо перезагрузить.

У клиента должно быть значение сессии character_set_client, идентичное глобальному значению, которое было при загрузке таблицы правил, иначе сопоставление правил для этого клиента не сработает.

© 2025 Oracle
Licensed under the GPLv2 License.
https://docs.oracle.com/cd/E17952_01/mysql-5.7-en/rewriter-query-rewrite-plugin-usage.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API