要启用或禁用插件,请启用或禁用rewriter_enabled
系统变量。默认情况下,重写
插件在安装时启用(参见第5.6.4.1节“安装或卸载Rewriter查询重写插件”).要显式设置初始插件状态,可以在服务器启动时设置该变量。例如,要在选项文件中启用插件,可以使用以下代码行:
(mysqld) rewriter_enabled =
也可以在运行时启用或禁用插件:
SET GLOBAL rewriter_enabled = ON;SET GLOBAL rewriter_enabled = OFF;
假设重写
插件被启用时,它检查并可能修改服务器接收到的每个可重写语句。插件根据其内存中的重写规则缓存来决定是否重写语句rewrite_rules
表格query_rewrite
数据库。
这些陈述可以重写:
独立语句和准备语句都可能被重写。在视图定义或存储程序中发生的语句不会被重写。
对象添加规则重写
插件,添加行到rewrite_rules
表,然后调用flush_rewrite_rules ()
将规则从表加载到插件的存储过程。下面的例子创建了一个简单的规则来匹配选择单个文字值的语句:
INSERT INTO query_rewrite。rewrite_rules(pattern, replacement) VALUES('SELECT ?', 'SELECT ? + 1');
生成的表内容如下所示:
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
该规则指定一个模式模板来指示选择
要匹配的语句,以及指示如何重写匹配语句的替换模板。但是,将规则添加到rewrite_rules
表不充分引起的重写
插件使用的规则。你必须调用flush_rewrite_rules ()
将表内容加载到插件的内存缓存中:
调用query_rewrite.flush_rewrite_rules();
如果重写规则似乎不能正常工作,请确保通过调用重新加载了规则表flush_rewrite_rules ()
.
当插件从规则表中读取每个规则时,它从模式和摘要哈希值中计算一个规范化的(语句摘要)表单,并使用它们更新normalized_pattern
而且pattern_digest
列:
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 ?
有关语句摘要、规范化语句和摘要哈希值的信息,请参见第27.10节“性能模式语句摘要和抽样”.
如果由于某些错误而无法加载规则,则调用flush_rewrite_rules ()
产生一个错误:
调用query_rewrite.flush_rewrite_rules();错误1644(45000):某些规则加载失败。
当发生这种情况时,插件将错误消息写入消息
列的规则行来传达问题。检查rewrite_rules
表中包含非零
消息
列值,以查看存在什么问题。
模式使用与准备语句相同的语法(参见第13.5.1节,“PREPARE语句”).在模式模板中,?
字符充当匹配数据值的参数标记。参数标记只能在数据值应该出现的地方使用,而不能用于SQL关键字、标识符等。的?
字符不应该用引号括起来。
与模式一样,替换可以包含?
字符。对于匹配模式模板的语句,插件将重写它,替换?
参数标记中的替换使用模式中相应标记匹配的数据值。结果是一个完整的语句字符串。该插件要求服务器解析它,并将结果作为重写语句的表示形式返回给服务器。
添加并加载规则后,根据语句是否匹配规则模式,检查是否发生重写:
mysql> SELECT PI();+----------+ | π () | +----------+ | 3.141593 | +----------+ 1行组(0.01秒)mysql >选择10;+--------+ | 10 + 1 | +--------+ | 11 | +--------+ 1行集,警告(0.00秒)
第一个不重写选择
陈述,但对第二句有意义。第二个表述说明了当重写
插件重写一个语句,它产生一个警告消息。要查看消息,请使用显示警告
:
mysql > \ G显示警告 *************************** 1。行***************************级别:备注代码:1105消息:查询“SELECT 10”被查询重写插件改写为“SELECT 10 + 1”
一条语句不需要重写为同一类型的语句。下面的示例加载一个重写规则删除
语句更新
声明:
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();
若要启用或禁用现有规则,请修改其启用
列并将表重新加载到插件中。禁用规则1:
更新query_rewrite。rewrite_rulesSET enabled = 'NO' WHERE id = 1; CALL query_rewrite.flush_rewrite_rules();
这使您可以在不将规则从表中删除的情况下禁用该规则。
重新启用规则1:
更新query_rewrite。rewrite_rulesSET enabled = 'YES' WHERE id = 1; CALL query_rewrite.flush_rewrite_rules();
的rewrite_rules
表包含pattern_database
列重写
用于匹配没有数据库名限定的表名:
如果对应的数据库名和表名相同,语句中的限定表名与模式中的限定表名匹配。
只有当默认数据库相同时,语句中的非限定表名才匹配模式中的非限定表名
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,并且有必要更具体地指明ID的类型id
列表示)。
更改意味着应用程序必须引用user_id
而不是id
在在哪里
条款。但如果有旧的应用程序无法编写更改选择
它们生成的查询将不再正常工作。的重写
插件可以解决这个问题。要匹配和重写语句,无论它们是否限定表名,添加以下两条规则并重新加载规则表:
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();
重写
使用第一条规则匹配使用限定表名的语句。它使用第二个来匹配使用非限定名称的语句,但只有在默认数据库为的情况下appdb
(价值在pattern_database
).
的重写
插件使用语句摘要和摘要哈希值来匹配进入的语句与重写规则的阶段。的max_digest_length
系统变量决定用于计算语句摘要的缓冲区的大小。较大的值使计算摘要能够区分较长的语句。较小的值使用较少的内存,但增加了较长的语句与相同摘要值发生冲突的可能性。
该插件将每个语句与重写规则匹配如下:
计算语句摘要哈希值并将其与规则摘要哈希值进行比较。这可能会出现假阳性,但可以作为快速排斥测试。
如果语句摘要哈希值匹配任何模式摘要哈希值,则将语句的规范化(语句摘要)形式与匹配规则模式的规范化形式相匹配。
如果规范化语句匹配一条规则,则比较语句和模式中的文字值。一个
?
模式中的字符匹配语句中的任何文字值。如果语句准备了一个语句,?
在模式上也很匹配?
在声明中。否则,对应的字面量必须相同。
如果多条规则匹配一条语句,则插件使用哪一条规则重写该语句是不确定的。
如果模式包含的标记比替换的标记多,插件将丢弃多余的数据值。如果模式包含的标记少于替换,则是错误。插件在加载规则表时注意到这一点,并向消息
列的规则行通信问题,并设置Rewriter_reload_error
状态变量为在
.
预处理语句在解析时重写(即在它们准备时),而不是在以后执行时重写。
准备语句不同于非准备语句,因为它们可能包含?
字符作为参数标记。匹配?
在准备好的陈述中,a重写
模式必须包含?
在同一个地方。假设重写规则具有以下模式:
选择?,3
下表显示了几个准备好的选择
语句以及规则模式是否与它们匹配。
事先准备好的声明中 | 模式是否与语句匹配 |
---|---|
PREPARE AS 'SELECT 3,3 ' |
是的 |
PREPARE s AS 'SELECT ?, 3' |
是的 |
PREPARE s AS 'SELECT 3, ?' |
没有 |
PREPARE s AS 'SELECT ?, ?' |
没有 |
的重写
Plugin通过几个状态变量来提供关于其操作的信息:
显示全局状态为“Rewriter%”;+-----------------------------------+-------+ | Variable_name |值 | +-----------------------------------+-------+ | Rewriter_number_loaded_rules | 1 | | Rewriter_number_reloads | 5 | | Rewriter_number_rewritten_queries | 1 | | Rewriter_reload_error | | +-----------------------------------+-------+
有关这些变量的描述,请参见第5.6.4.3.4节“重写查询重写插件状态变量”.
方法加载规则表时flush_rewrite_rules ()
存储过程中,如果某个规则发生错误,则调用
语句产生错误,插件将设置Rewriter_reload_error
状态变量为在
:
调用query_rewrite.flush_rewrite_rules();错误1644(45000):某些规则加载失败。查询全局状态:Rewriter_reload_error;+-----------------------+-------+ | Variable_name |值 | +-----------------------+-------+ | Rewriter_reload_error |上 | +-----------------------+-------+
在这种情况下,检查rewrite_rules
表中包含非零
消息
列值,以查看存在什么问题。
当rewrite_rules
表加载到重写
类的当前全局值来解释语句character_set_client
系统变量。如果全局character_set_client
值更改后,规则表必须重新加载。
客户端必须有会话character_set_client
值与装入规则表时的全局值相同,或规则匹配对该客户端无效。