[Source reading of HintSQLHandler of Mycat1.6]

 MyCat provides a solution for Sql statements that are not supported by itself - add an extra piece of code organized by annotated SQL before the SQL statement to be executed, so that Sql can be executed correctly, this code is called "annotation" . The use of annotations is equivalent to making a layer of transparent proxy forwarding for SQL statements that are not supported by mycat, and directly handing them over to the target data node for SQL statement execution. The annotated SQL is used to determine the data node that finally executes the SQL. The form of the annotation is:

/*!mycat: sql=Annotate Sql statement*/

Annotations are used in the following way:

/*!mycat: sql=Annotate Sql statement*/Real execute Sql

 

1. Principle introduction: 

The process of MyCat executing SQL statements is to first perform SQL parsing processing, parse out the shard information (routing information), and then execute it in the physical database corresponding to the shard; if the incoming SQL statement cannot be parsed by MyCat, MyCat will not The annotation tells MyCat to perform parsing processing according to the SQL in the annotation (called the annotation SQL). After parsing the fragmentation information, it sends the SQL statement to be executed after the annotation (called the original SQL). Go to the physical library corresponding to the shard to execute. 

As can be seen from the above principle, the annotation only tells MyCat where to execute the original SQL; therefore, before using the annotation, it is necessary to clearly know which shard to execute the original SQL, and then also point to the shard in the annotated SQL, so that to use! The sharding_id=10010 in the example indicates the sharding information. 

It should be noted that if the annotation SQL does not specify a specific shard, for example, the annotation SQL in the example does not add the condition of sharding_id=10010, MyCat will send the original SQL to all shards where the persons table is located for execution. , if the consequence of this is an insert statement, there will be duplicate records on multiple shards, and the same query, update, and delete operations will also get wrong results!

 

 The inheritance relationship

HintHandler  has five subclasses, HintCatletHandler, HintDataNodeHandler, HintMasterDBHandler, HintSchemaHandler, HintSQLHandler

/**

 * Do route parsing according to the content of the specified type in the comment

 * 

 */

public interface HintHandler {

 

public RouteResultset route(SystemConfig sysConfig, SchemaConfig schema,

                                int sqlType, String realSQL, String charset, 

ServerConnection sc,LayerCachePool cachePool, 

String hintSQLValue, int hintSqlType, Map hintMap)throws SQLNonTransientException;

--This method has too many parameters and is not friendly enough

}



 

/**

 * Handle the case where the type in the comment is sql (do route parsing according to the sql in the comment, not the actual sql)

 */

public class HintSQLHandler implements HintHandler {}

 

/**

 * Handle the case where the type in the annotation is schema (resolve the route according to the specified schema)

 */

public class HintSchemaHandler implements HintHandler{}

 

/**

 * Handling sql hint: mycat:db_type=master/slave<br/>

 * In the later stage, we may consider adding mycat:db_type=slave_newest to realize the slave with the smallest walking delay

 * @author [email protected]

 */

// /*#mycat:db_type=master*/

// /*#mycat:db_type=slave*/

// /*#mycat:db_type=slave_newest*/

// 强制走 master 和 强制走 slave

public class HintMasterDBHandler implements HintHandler {}

 

/**

 * 处理注释中类型为datanode 的情况

 * 

 * @author zhuam

 */

public class HintDataNodeHandler implements HintHandler{}

 

/**

 * 处理注释中类型为catlet 的情况,每个catlet为一个用户自定义Java代码类,用于进行复杂查询SQL(只能是查询SQL)的自定义执行过程,

 * 目前主要用于跨分片Join的人工智能编码

 */

public class HintCatletHandler implements HintHandler {}

 

 

三、应用示例

 

/*#mycat:db_type=master*/ select * from travelrecord

 

 

 

/*!mycat: sql=select 1 from test */create table test2(id int);

如select 1 from 表,注解内语句查出来的数据在哪个分片,数据在那个节点往哪个节点建. 

 

 

 

配置了Mycat读写分离后,默认查询都会从读节点获取数据,但是有些场景需要获取实时数据,如果从读节点获取数据可能因延时而无法实现实时,Mycat支持通过注解/balance/来强制从写节点查询数据:

a. 事务内的SQL,默认走写节点,以注解/*balance*/开头,则会根据schema.xml的dataHost标签属性的balance=“1”或“2”去获取节点 

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

 /*balance*/ select a.* from customer a where a.company_id=1;

 

 

 

多租户支持 

通过注解方式在配置多个schema情况下,指定走哪个配置的schema。 

web部分修改: a.在用户登录时,在线程变量(ThreadLocal)中记录租户的id b.修改jdbc的实现:在提交sql时,从ThreadLocal中获取租户id, 添加sql 注释,把租户的schema 放到注释中。例如:/!mycat : schema = test_01 / sql ; 

在db前面建立proxy层,代理所有web过来的数据库请求。proxy层是用mycat实现的,web提交的sql过来时在注释中指定schema, proxy层根据指定的schema转发sql请求。

 /*!mycat : schema = test_01 */ sql ;

 

 

 多表

 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;

 

 

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326448633&siteId=291194637