在机场继续努力一把,学习了下MySQL query rewrite这个插件,感觉还不错,j简答测试了下,已经找到Oracle FGA的影子了。
MySQL的插件还是很丰富的,大多数都在lib目录下,我们可以使用show pugins的方式来查看一个插件清单,但是在share目录下有一个插件query rewrite却是比较特殊,非常低调。这个插件是MySQL 5.7.6开始支持,它的安装方式不大一样,是需要我们去运行一个脚本来初始化的。
当然实际安装这个插件的时候,也是会在lib目录下去调用rewrite.so的插件,还会创建一个辅助表,一个函数还有一个存储过程。
CREATE TABLE IF NOT EXISTS query_rewrite.rewrite_rules (。。。。
INSTALL PLUGIN rewriter SONAME 'rewriter.so';
CREATE FUNCTION load_rewrite_rules RETURNS STRING
SONAME 'rewriter.so';
CREATE PROCEDURE query_rewrite.flush_rewrite_rules()。。。。
初始化的过程如下,分分钟即可搞定。
mysql> source install_rewriter.sql
Query OK, 1 row affected (0.09 sec)
Query OK, 0 rows affected (0.03 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.01 sec)
Query OK, 0 rows affected (0.00 sec)
Query OK, 0 rows affected (0.00 sec)
当然安装好之后,数据库层面会有一个对应的参数rewrite_enabled,我们也可以固化配置在my.cnf配置里面。
SHOW GLOBAL VARIABLES LIKE 'rewriter_enabled';
如果是在my.cnf里面,则配置如下:
rewriter_enabled=ON
这个插件怎么用呢,我们可以给出一个案例来,比如我们在数据库test2下有个表test_data,这个表的数据很关键,而且数据量很大,我们不希望大家查到所有的数据,那么可以考虑使用这个插件,简单的说,它算是一个审计范畴的功能。
比如我们希望执行的SQL语句如下: select * from test2.test_data,那么我们希望自动解析为select * from test2.test_data limit 10
我们可以这样配置一下。
在这个配置表rewrite_rules里面插入一条记录。
mysql> insert into rewrite_rules(pattern, replacement) values('select * from test2.test_data ' , 'select * from test2.test_data limit 10');
Query OK, 1 row affected (0.08 sec)
然后刷新存储过程
mysql> call flush_rewrite_rules(); Query OK, 0 rows affected (0.08 sec)
再次查看存储过程会发现里面已经生成了相应的配置信息。
mysql> select *from rewrite_rules\G
*************************** 1. row ***************************
id: 4
pattern: select * from test2.test_data
pattern_database: NULL
replacement: select * from test2.test_data limit 10
enabled: YES
message: NULL
pattern_digest: a347817f163d8579ddfe7d3e06b59eeb
normalized_pattern: select `*` from `test2`.`test_data`
1 row in set (0.00 sec)
当然我们可以实现的更加完整,等下再补充。
我们插入一些数据,比如临界点,我们插入了11条数据。
mysql> insert into test_data values(1,'aa'),(2,'bb'),(3,'cc'),(4,'dd'),(5,'ee'),(6,'ff'),(7,'gg'),(8,'hh'),(9,'ii'),(10,'jj'),(11,'kk');
Query OK, 11 rows affected (0.07 sec)
Records: 11 Duplicates: 0 Warnings: 0
我们使用如下的SQL来查询,就会发现已经自动做了转换,截取了10条数据。
mysql> select *from test2.test_data;
+------+------+
| id | name |
+------+------+
| 1 | aa |
| 2 | bb |
| 3 | cc |
| 4 | dd |
| 5 | ee |
| 6 | ff |
| 7 | gg |
| 8 | hh |
| 9 | ii |
| 10 | jj |
+------+------+
10 rows in set, 1 warning (0.00 sec)
查看更多的信息,如下:
mysql> show warnings\G
*************************** 1. row ***************************
Level: Note
Code: 1105
Message: Query 'select *from test2.test_data' rewritten to 'select * from test2.test_data limit 10' by a query rewrite plugin
1 row in set (0.00 sec)
可以看到插件已经生效了。
当然如果我们的配置不符合标准,则运行存储过程的时候就会抛错。
比如:
mysql> insert into rewrite_rules(pattern, replacement) values('select * from test2.?' , 'select * from test2.? limit 10');
Query OK, 1 row affected (0.08 sec)
mysql> create database test2;
Query OK, 1 row affected (0.07 sec)
mysql>
mysql> create table test_data (id int,name varchar(30));
Query OK, 0 rows affected (0.03 sec)
mysql> insert into test_data values(1,'aa'),(2,'bb');
Query OK, 2 rows affected (0.08 sec)
Records: 2 Duplicates: 0 Warnings: 0
mysql> call flush_rewrite_rules();
ERROR 1644 (45000): Loading of some rule(s) failed.
mysql>
我们可以查看更详细的信息。
mysql> select *from rewrite_rules \G
*************************** 1. row ***************************
id: 1
pattern: select * from test2.?
pattern_database: NULL
replacement: select * from test2.? limit 10
enabled: YES
message: Parse error in pattern: >>You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 1<<
pattern_digest: NULL
normalized_pattern: NULL
1 row in set (0.00 sec)