返回ProxySQL系列文章:http://www.cnblogs.com/f-ck-need-u/p/7586194.htmlhtml
在mysql_query_rules表中,有两个特殊字段"flagIN"和"flagOUT",它们分别用来定义规则的入口和出口,从而实现链式规则(chains of rules)。mysql
链式规则的实现方式以下:正则表达式
flagOUT=flagIN
的规则,则匹配该规则。该规则是链式规则中的另外一条规则。经过下面两张图,应该很容易理解链式规则的生效方式。sql
必须注意,规则是按照rule_id的大小顺序进行的。且并不是只有apply=1时才会应用规则,当无规则可匹配,或者某规则的flagIN和flagOUT值相同,都会应用最后一次被评估的规则。app
如下几个示例,能够解释生效规则:测试
# rule_id=3 生效 +---------+-------+--------+---------+ | rule_id | apply | flagIN | flagOUT | +---------+-------+--------+---------+ | 1 | 0 | 0 | 23 | | 2 | 0 | 23 | 23 | | 3 | 0 | 23 | NULL | +---------+-------+--------+---------+ # rule_id=2 生效 +---------+-------+--------+---------+ | rule_id | apply | flagIN | flagOUT | +---------+-------+--------+---------+ | 1 | 0 | 0 | 23 | | 2 | 0 | 23 | 23 | | 3 | 0 | 24 | NULL | +---------+-------+--------+---------+ # rule_id=2 生效,由于匹配完rule_id=2后,还打着flagOUT=23标记 +---------+-------+--------+---------+ | rule_id | apply | flagIN | flagOUT | +---------+-------+--------+---------+ | 1 | 0 | 0 | 23 | | 2 | 0 | 23 | NULL | | 3 | 1 | 24 | NULL | +---------+-------+--------+---------+ # rule_id=3 生效,由于匹配完rule_id=2后,还打着flagOUT=23标记 +---------+-------+--------+---------+ | rule_id | apply | flagIN | flagOUT | +---------+-------+--------+---------+ | 1 | 0 | 0 | 23 | | 2 | 0 | 23 | NULL | | 3 | 1 | 23 | NULL | +---------+-------+--------+---------+
有了普通规则匹配方式,为何还要设计链式规则呢?虽然ProxySQL经过正则表达式实现了很灵活的规则匹配模式,但需求老是变幻无穷的,有时候仅经过一条正则匹配规则和替换规则很难实现比较复杂的要求,例如sharding时。设计
链式规则除了经常使用的屡次替换,还可巧用于屡次匹配。code
本文简单演示一下链式规则,不具备实际意义,只为后面ProxySQL实现sharding的文章作基础知识铺垫。htm
2个测试库,共4张表test{1,2}.t{1,2}。blog
mysql> select * from test1.t1; +------------------+ | name | +------------------+ | test1_t1_malong1 | | test1_t1_malong2 | | test1_t1_malong3 | +------------------+ mysql> select * from test1.t2; +------------------+ | name | +------------------+ | test1_t2_malong1 | | test1_t2_malong2 | | test1_t2_malong3 | +------------------+ mysql> select * from test2.t1; +--------------------+ | name | +--------------------+ | test2_t1_xiaofang1 | | test2_t1_xiaofang2 | | test2_t1_xiaofang3 | +--------------------+ mysql> select * from test2.t2; +--------------------+ | name | +--------------------+ | test2_t2_xiaofang1 | | test2_t2_xiaofang2 | | test2_t2_xiaofang3 | +--------------------+
如今借用链式规则,一步一步地将对test1.t1表的查询路由到test2.t2表的查询。再次声明,此处示例毫无实际意义,仅为演示链式规则的基本用法。
大体链式匹配的过程为:
test1.t1 --> test1.t2 --> test2.t1 --> test2.t2
如下是具体插入的规则:
delete from mysql_query_rules; select * from stats_mysql_query_digest_reset where 1=0; insert into mysql_query_rules (rule_id,active,apply,flagIN,flagOUT,match_pattern,replace_pattern) values (1,1,0,0,23,"test1\.t1","test1.t2"); insert into mysql_query_rules (rule_id,active,apply,flagIN,flagOUT,match_pattern,replace_pattern) values (2,1,0,23,24,"test1\.t2","test2.t1"); insert into mysql_query_rules (rule_id,active,apply,flagIN,flagOUT,match_pattern,replace_pattern,destination_hostgroup) values (3,1,1,24,NULL,"test2\.t1","test2.t2",30); load mysql query rules to runtime; save mysql query rules to disk; admin> select rule_id, apply, flagIN, flagOUT, match_pattern, replace_pattern, destination_hostgroup DH from mysql_query_rules; +---------+-------+--------+---------+---------------+-----------------+------+ | rule_id | apply | flagIN | flagOUT | match_pattern | replace_pattern | DH | +---------+-------+--------+---------+---------------+-----------------+------+ | 1 | 0 | 0 | 23 | test1\.t1 | test1.t2 | NULL | | 2 | 0 | 23 | 24 | test1\.t2 | test2.t1 | NULL | | 3 | 1 | 24 | NULL | test2\.t1 | test2.t2 | 30 | +---------+-------+--------+---------+---------------+-----------------+------+
查询test1.t1表,测试结果。
[root@xuexi ~]# mysql -uroot -pP@ssword1! -h127.0.0.1 -P6033 -e "select * from test1.t1;" +--------------------+ | name | +--------------------+ | test2_t2_xiaofang1 | <-- 查询返回结果为test2.t2内容 | test2_t2_xiaofang2 | | test2_t2_xiaofang3 | +--------------------+ admin> select * from stats_mysql_query_rules; +---------+------+ | rule_id | hits | +---------+------+ | 1 | 1 | <-- 3条规则全都命中 | 2 | 1 | | 3 | 1 | +---------+------+ admin> select hostgroup,digest_text from stats_mysql_query_digest; +-----------+----------------------------------+ | hostgroup | digest_text | +-----------+----------------------------------+ | 30 | select * from test2.t2 | <-- 路由目标hg=30 +-----------+----------------------------------+
显然,已经按照预想中的方式进行匹配、替换、路由。
一个问题:若是查询的是test1.t2表或test2.t1表,会进行链式匹配吗?
答案是不会,由于rule_id=2
和rule_id=3
这两个规则的flagIN都是非0值,而每一个SQL语句初始时只进入flagIN=0
的规则。
此外还需注意,当某语句未按照咱们的指望途经全部的链式规则,则可能会根据destination_hostgroup
字段的值直接路由出去,即便没有指定该字段值,还有用户的默认路由目标组,或者基于端口的路由目标。因此,在写链式规则时,应当尽量地针对某一类型的语句进行完完整整的定制,保证这类语句能途经咱们所指望的全部规则。