SQL 拦截是一个比较有用的高级技巧,用户可以写一个 java 类,将传入 MyCAT 的 SQL 进行改写然后交给Mycat 去执行,此技巧可以完成如下一些特殊功能:
- 捕获和记录某些特殊的 SQL;
- 记录 sql 查找异常;
- 出于性能优化的考虑,改写 SQL,比如改变查询条件的顺序或增加分页限制;
- 将某些 Select SQL 强制设置为 Read 模式,走读写分离(很多事务框架很难剥离事务中的 Select SQL;
- 后期 Mycat 智能优化,拦截所有 sql 做智能分析,自动监控节点负载,自动优化路由,提供数据库优化建议。
SQL 拦截的原理是在路由之前拦截 SQL,然后做其他处理,完了之后再做路由,执行,如下图所示:
默认的拦截器实现了 Mysql 转义字符的过滤转换,非默认拦截器只有一个拦截记录 sql 的拦截器。
a. 默认 SQL 拦截器:
配置:
<system>
<property name="sqlInterceptor">io.mycat.interceptor.impl.DefaultSqlInterceptor</property>
</system>
源码:
/**
* escape mysql escape letter
*/
@Override
public String interceptSQL(String sql, int sqlType) {
if (sqlType == ServerParse.UPDATE || sqlType == ServerParse.INSERT||sqlType ==
ServerParse.SELECT||sqlType == ServerParse.DELETE) {
return sql.replace("\\'", "''");
} else {
return sql;
}
}
b. 捕获记录 sql 拦截器配置:
<system>
<property name="sqlInterceptor">io.mycat.interceptor.impl.StatisticsSqlInterceptor</property>
<property name="sqlInterceptorType">select,update,insert,delete</property>
<property name="sqlInterceptorFile">E:/mycat/sql.txt</property>
</system>
sqlInterceptorType : 拦截 sql 类型
sqlInterceptorFile : sql 保存文件路径
注意:捕获记录 sql 拦截器的配置只有 1.4 及其以后可用,1.3 无本拦截。
如果需要实现自己的 sql 拦截,只需要将配置类改为自己配置即可:
1.定义自定义类 implements SQLInterceptor ,然后改写 sql 后返回。
2.将自己实现的类放入 catlet 目录,可以为 class 或 jar。
3.配置配置文件:
<system>
<property name="sqlInterceptor">io.mycat.interceptor.impl.自定义 class</property>
<!--其他配置-->
</system>