mycat系列-Mycat注解
注解原理
概念:
MyCat对自身不支持的Sql语句提供了一种解决方案——在要执行的SQL语句前添加额外的一段代码,这样Sql就能正确执行,这段代码称之为“注解”。注解的形式是
/*!mycat: sql=Sql语句*/
使用时将=号后的“Sql语句”替换为需要的Sql语句即可,后面会提到具体的用法。
原理:
MyCat执行SQL语句的流程是先进行SQL解析处理,解析出分片信息(路由信息)后,然后到该分片对应的物理库上去执行;若传入的SQL语句MyCat无法解析,则MyCat不会去执行;而注解则是告诉MyCat按照注解内的SQL(称之为注解SQL)去进行解析处理,解析出分片信息后,将注解后真正要执行的SQL语句(称之为原始SQL)发送到该分片对应的物理库上去执行。
从上面的原理可以看到,注解只是告诉MyCat到何处去执行原始SQL;因而使用注解前,要清楚的知道该原始SQL去哪个分片执行,然后在注解SQL中也指向该分片,这样才能使用!例子中的sharding_id=10010 即是指明分片信息的。
需要说明的是,若注解SQL没有能明确到具体某个分片,譬如例子中的注解SQL没有添加sharding_id=10010这个条件,则MyCat会将原始SQL发送到persons表所在的所有分片上去执行去,这样造成的后果若是插入语句,则在多个分片上都存在重复记录,同样查询、更新、删除操作也会得到错误的结果!
解决问题:
1. MySql不支持的语法结构,如insert …select…
2. 同一个实例内的跨库关联查询,如用户库和平台库内的表关联
3. 存储过程调用。
4. 表,存储过程创建。
注解规范
1.注解SQL使用select语句,不允许使用delete/update/insert等语句;虽然delete/update/insert 等语句也能用在注解中,但这些语句在Sql处理中有额外的逻辑判断,从性能考虑,请使用select语句
2.注解SQL禁用表关联语句
3.注解SQL尽量用最简单的SQL语句,如select id from tab_a where id=’10000’
4.无论是原始SQL还是注解SQL,禁止DDL语句
5.能不用注解的尽量不用
6.详细要求见下表
补充说明:
使用注解并不额外增加MyCat的执行时间;从解析复杂度以及性能考虑,注解SQL应尽量简单。至于一个SQL使用注解和不使用注解的性能对比,不存在参考意义,因为前提是MyCat不支持的SQL才使用注解。
注解使用示例
1. Mycat端执行存储创建表或存储过程为:
存储过程:
/*!mycat: sql=select 1 from test */ CREATE PROCEDURE `test_proc`() BEGIN END ;
表:
/*!mycat: sql=select 1 from test */create table test2(id int);
注意注解中语句是节点的表请替换成自己表如select 1 from 表 ,注解内语句查出来的数据在哪个分片,数据在那个节点往哪个节点建.
2. 特殊语句自定义分片:
/*!mycat: sql=select 1 from test */insert into t_user(id,name) select id,name from t_user2;
3. 读写分离
配置了,Mycat读写分离后,默认查询会到都节点,获取数据,但是有些场景需要实时获取,如果读读节点,有可能会有延时,Mycat支持通过注解/*balance*/来获取读写:
a. 事务内的SQL,默认走写节点,以注释/*balance*/开头,则会根据balance=“1”或“2”去获取
b. 非事务内的SQL,开启读写分离默认根据balance=“1”或“2”去获取,以注释/*balance*/开头则会走写解决部分已经开启读写分离,但是需要强一致性数据实时获取的场景走写
4. 多表ShareJoin
/*!mycat:catlet=demo.catlets.ShareJoin */ select a.*,b.id, b.name as tit from customer a,company b on a.company_id=b.id;
5. 多租户支持
通过注解方式在配置多个schema情况下,指定走哪个配置的schema。
1.web部分修改:
a.在用户登录时,在线程变量(ThreadLocal)中记录租户的id
b.修改jdbc的实现:在提交sql时,从ThreadLocal中获取租户id, 添加sql 注释,把租户的schema 放到注释中。例如:/*!mycat : schema = test_01 */ sql ;
2.在db前面建立proxy层,代理所有web过来的数据库请求。proxy层是用mycat实现的,web提交的sql过来时在注释中指定schema, proxy层根据指定的schema转发sql请求。
/*!mycat : schema = test_01 */ sql ;