Spec-Zone.ru › MySQL 8.4

7.6.4.2 Использование плагина переписывания запросов Rewriter

Для включения или отключения плагина, включите или отключите системную переменную rewriter_enabled. По умолчанию, плагин Rewriter включён при установке (см. Раздел 7.6.4.1, «Установка или удаление плагина переписывания запросов Rewriter»). Для явного задания начального состояния плагина, вы можете установить переменную при запуске сервера. Например, для включения плагина в файле настроек, используйте следующие строки:

[mysqld]
rewriter_enabled=ON

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

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

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

Эти операторы подлежат переписыванию: SELECT, INSERT, REPLACE, UPDATE и DELETE.

Автономные операторы и подготовленные операторы подлежат переписыванию. Операторы, встречающиеся в определениях представлений или хранимых процедурах, не подлежат переписыванию.

Операторы, выполняемые пользователями с привилегией SKIP_QUERY_REWRITE, не подлежат переписыванию, при условии, что системная переменная rewriter_enabled_for_threads_without_privilege_checks установлена в значение OFF (значение по умолчанию ON). Это можно использовать для управляющих операторов и операторов, которые должны быть реплицированы без изменений, таких как операторы из SOURCE_USER, указанные в CHANGE REPLICATION SOURCE TO. Это также относится к операторам, выполняемым программами клиентов MySQL, включая mysqlbinlog, mysqladmin и mysqldump; по этой причине вы должны предоставить SKIP_QUERY_REWRITE пользователю или пользователям, используемым этими утилитами для подключения к MySQL.

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

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

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

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

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

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

Для добавления правил для плагина 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().

Когда плагин считывает каждое правило из таблицы правил, он вычисляет нормализованную форму (хеш-сумму оператора) из шаблона и значение хеша дайджеста и использует их для обновления столбцов 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: d1b44b0c19af710b5a679907e284acd2ddc285201794bc69a2389d77baedddae
normalized_pattern: select ?

Дополнительную информацию о хешировании операторов, нормализованных операторах и значениях хеша дайджеста см. в разделе 29.10, «Хеш-суммы операторов и выборки Performance Schema».

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

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

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

Шаблоны используют тот же синтаксис, что и подготовленные операторы (см. раздел 15.5.1, «Оператор PREPARE»). Внутри шаблона ? символы действуют как маркеры параметров, которые соответствуют значениям данных. Символы ? не должны быть заключены в кавычки. Маркеры параметров могут использоваться только там, где должны появляться значения данных, и они не могут использоваться для SQL-ключевых слов, идентификаторов, функций и т. д. Плагин анализирует оператор, чтобы определить литеральные значения (как определено в разделе 11.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

Оператор необязательно должен быть переписан в оператор того же типа. Следующий пример загружает правило, которое переписывает операторы DELETE в операторы UPDATE:

INSERT INTO query_rewrite.rewrite_rules (pattern, replacement)
VALUES('DELETE FROM db1.t1 WHERE col = ?',
       'UPDATE db1.t1 SET col = NULL WHERE col = ?');
CALL query_rewrite.flush_rewrite_rules();

Чтобы включить или отключить существующее правило, измените его столбец 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. Если нормализованный оператор соответствует правилу, сравните литеральные значения в операторе и шаблоне. Символ ? в шаблоне соответствует любому литеральному значению в операторе. Если оператор подготавливает оператор, то ? в шаблоне также соответствует ? в операторе. В противном случае соответствующие литералы должны быть одинаковыми.

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

Если шаблон содержит больше маркеров, чем замена, плагин отбрасывает избыточные значения данных. Если шаблон содержит меньше маркеров, чем замена, это ошибка. Плагин замечает это при загрузке таблицы правил, записывает сообщение об ошибке в столбец 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    |
+-----------------------------------+-------+

Описание этих переменных см. в разделе 7.6.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-8.4-en/rewriter-query-rewrite-plugin-usage.html

Spec-Zone.ru

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