MySQL query rewrite插件簡單測試

在機場繼續努力一把,學習了下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)