MyCat注解使用指南

MyCat注解使用指南

定义

         MyCat对自身不支持的Sql语句提供了一种解决方案——在要执行的SQL语句前添加额外的一段代码,这样Sql就能正确执行,这段代码称之为“注解”。注解的形式是

         /*!mycat: sql=Sql语句*/

         使用时将=号后的“Sql语句”替换为需要的Sql语句即可,后面会提到具体的用法。

例子

         假设需要执行的语句是

        Insert into persons(id,name,sharding_id) values(1,’郭靖’,10010),(2,’黄蓉’,10010);

鉴于路由分析的原因,MyCat暂不支持这种语句的执行,如果一定需要执行这种语句,可在这段sql代码前添加

         /*!mycat: sql=select id from persons where sharding_id=10010 */

语句变为如下形式即可执行

         /*!mycat: sql=select id from persons where sharding_id=10010 */insert into persons(id,name,sharding_id) values(1,’郭靖’,10010),(2,’黄蓉’,10010);

        

原理

         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表所在的所有分片上去执行去,这样造成的后果若是插入语句,则在多个分片上都存在重复记录,同样查询、更新、删除操作也会得到错误的结果!

 

解决问题

Ø  MySql不支持的语法结构,如insert… values(),()…  insert …select等

Ø  同一个实例内的跨库关联查询,如用户库和平台库内的表关联

Ø  存储过程调用

 

注解规范

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.         详细要求见下表

 

原始Sql

注解Sql

备注

Select

1.          选择能唯一确定分片的主表,如与用户表关联的时候可以选择用户表

2.          若是业务需要在主表所在的各个分片上都执行可以不加能确定分片的条件

 

Insert

Ø  对于分片表

1.          使用insert的表做注解SQL

2.          注解SQL必须能确认具体到某个分片

3.          原始SQL插入的字段必须包含分片字段

4.          原始SQL中包含的分片字段和注解SQL中的分片字段确定的分片务必要一致

5.          对于insert … select这种语句,请务必确认插入的记录都在当前查找到的分片上

Ø  非分片表

1.          注解SQL必须能具体确认到某个分片

2.          注解SQL包含的分片字段其分片上必须包含这个非分片表

 

Delete

1.          对于分片表使用要删除记录的表做注解SQL

2.          根据业务需求添加注解Sql的分片字段值

 

Update

1.          对于分片表用所要更新的表做注解SQL

2.          禁止更新分片表的分片列

3.          根据业务需要添加注解Sql的分片字段值

 

Call

1.          若是要在所有的分片上都执行存储过程,则使用一个在所有分片上都包含的表,不添加任何分片条件

2.          若是单个分片执行,使用能确认到这个分片的表以及分片条件

调用存储过程

补充说明

         使用注解并不额外增加MyCat的执行时间;从解析复杂度以及性能考虑,注解SQL应尽量简单。至于一个SQL使用注解和不使用注解的性能对比,不存在参考意义,因为前提是MyCat不支持的SQL才使用注解。

 

如果执行存储创建表或存储过程为:

 存储过程:

/*!mycat: sql=select 1 */  CREATE DEFINER=`root`@`%` PROCEDURE `test_procaaaaaaaa`() BEGIN END  ;[enter]

表:/*!mycat: sql=select 1 */create table ttt(id int);注意注解中语句是节点的表请替换成自己表如select 1 from 表 ,查出来的数据在那个节点往哪个节点建



遗留问题

         使用注解后语句是分别到各个分片去执行,因而会造成一些遗留问题

Ø  Select语句:最终的结果只是简单的结果集合并,没有做处理,order by, group by, sum, min, max等均是未做处理的错误结果。(此问题已可通过修改MyCat源码解决)

Ø  Call语句:对于返回结果集的存储过程,暂不支持通过注解对其进行order by, group by, sum, min, max


读写分离:

  1. 事务内的SQL,默认走写节点,以注释/*balance*/开头,则会根据balance=“1” 或“2” 去获取
  2. 非事务内的SQL,开启读写分离默认根据balance=“1” 或“2” 去获取,以注释/*balance*/开头 则会走写 解决部分已经开启读写分离, 但是需要强一致性数据实时获取的场景走写

注解使用样例:

通过catlet支持跨分片复杂SQL实现以及存储过程支持等。使用方式主要通过mycat注释的方式来执行,如下:1. 跨分片联合查询注解支持:/*!mycat:catlet=demo.catlets.ShareJoin / select bu.,sg.* from base_user bu,sam_glucose sg where bu.id_=sg.user_id;注:sam_glucose 是跨分片表;2. 存储过程注解支持:/*!mycat: sql=select * from base_user where id_=1;*/ CALL proc_test();注:目前执行存储过程通过mycat注解的方式执行,注意需要把存储过程中的sql写到注解中;3. 批量插入与ID自增长结合的支持:/*!mycat:catlet=demo.catlets.BatchInsertSequence */ insert into sam_test(name_) values(‘t1’),(‘t2’);注: 此方式不需要在sql语句中显示的设置主键字段,程序在后台根据primaryKey配置的主键列,自动生成主键的sequence值并替换原sql中相关的列和值;4. 获取批量sequence值的支持:/*!mycat:catlet=demo.catlets.BatchGetSequence */SELECT mycat_get_seq(‘MYCAT_TEST’,100);注:此方法表示获取MYCAT_TEST表的100个sequence值,例如当前MYCAT_TEST表的最大sequence值为5000,则通过此方式返回的是5001,同时更新数据库中的MYCAT_TEST表的最大sequence值为5100.5.多租户/*!mycat :  schema = test_01 */ sql ;

1. 跨分片联合查询注解支持:
/*!mycat:catlet=demo.catlets.ShareJoin / select bu.,sg.* from base_user bu,sam_glucose sg where bu.id_=sg.user_id;
注:sam_glucose 是跨分片表;
2. 存储过程注解支持:
/*!mycat: sql=select * from base_user where id_=1;*/ CALL proc_test();
注:目前执行存储过程通过mycat注解的方式执行,注意需要把存储过程中的sql写到注解中;
3. 批量插入与ID自增长结合的支持:
/*!mycat:catlet=demo.catlets.BatchInsertSequence */ insert into sam_test(name_) values(‘t1’),(‘t2’);
注: 此方式不需要在sql语句中显示的设置主键字段,程序在后台根据primaryKey配置的主键列,自动生成主键的sequence值并替换原sql中相关的列和值;
4. 获取批量sequence值的支持:
/*!mycat:catlet=demo.catlets.BatchGetSequence */SELECT mycat_get_seq(‘MYCAT_TEST’,100);
注:此方法表示获取MYCAT_TEST表的100个sequence值,例如当前MYCAT_TEST表的最大sequence值为5000,则通过此方式返回的是5001,同时更新数据库中的MYCAT_TEST表的最大sequence值为5100.
5.多租户
/*!mycat :  schema = test_01 */ sql ;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值