DBA主宰一切请求,MySQL 查询重写
这个功能一年左右之前就以知晓,应该是5.7的高版本中。今天难得有兴致测试、随之也就总结一下。
安装
- 首先创建一个query_rewrite库, 库中一个rewrite_rules表。用来保存定义的改写规则。
- 安装rewriter插件,实现函数。
- 创建一个函数load_rewrite_rules的自定义函数,其实现为rewriter共享库。
- 创建一个存储过程,存储过程里面定义刷新查询改写缓存的方法。
- 从查询缓存集中移除所有查询缓存。(8.0移除了QueryCache,自然也就没有这个。)
mysql -udba_yix -p < /usr/local/mysql/share/install_rewriter.sql
mysql -udba_yix -p < /usr/local/mysql/share/uninstall_rewriter.sql
INSERT INTO query_rewrite.rewrite_rules (pattern, replacement) VALUES('SELECT ?', 'SELECT ? + 1');
CALL query_rewrite.flush_rewrite_rules();
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();
发现报了错。如果有报错,需要结合 query_rewrite.rewrite_rules表中的message字段查看原因。
这就是我们上面提到的在8.0.12之前只能改写select。
UPDATE query_rewrite.rewrite_rules SET enabled = 'NO' WHERE id = 1; CALL query_rewrite.flush_rewrite_rules();
重启则参考下面语句。
UPDATE query_rewrite.rewrite_rules SET enabled = 'YES' WHERE id = 1; CALL query_rewrite.flush_rewrite_rules();
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();
SELECT * FROM users WHERE appdb.id = id_value;
SELECT * FROM users WHERE id = id_value;
则重写器(rewriter)会使用第一条规则匹配第一条SQL。第二条规则匹配第二条SQL(前提是默认的数据库是appdb)。
SELECT ?, 3
Prepared Statement
|
Whether Pattern Matches Statement
|
PREPARE s AS ‘SELECT 3, 3’
|
Yes
|
PREPARE s AS ‘SELECT ?, 3’
|
Yes
|
PREPARE s AS ‘SELECT 3, ?’
|
No
|
PREPARE s AS ‘SELECT ?, ?’
|
No
|
重写器状态统计信息
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 | +-----------------------------------+-------+