注:文中使用版本为Mycat 1.6.5。
1、Mycat
正如官方所说,
Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务。由于前面讲的对数据进行分片处理之后,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构成了整个完整的数据库存储。
当然,Mycat没有自己的存储引擎,并不是完全意义的分布式数据库系统。
以下是官方的架构图。

我们可以清晰地看到MyCat的核心是“拦截sql并做解析、路由,结果集合并”。
但是,也如官方所设计的
Mycat 就是MySQL 最佳伴侣,它在一定程度上让MySQL 拥有了能跟Oracle PK 的能力。
MyCat的基因从Cobar开始,就是为MySQL为设计的。当你使用oracle作为物理库的时候,就会出现各种问题。
2、SQL解析问题
不论原有Mycat不支持的SQL语句,但oracle语法就很多不兼容,甚至无法正常运行。如insert into .... select ...语句不支持;blob大字段的insert/update在oracle环境有问题;不支持start with ... connect by....递归树语句;
如果你的系统有这些,要么在应用端改写掉,要么请放弃使用Mycat。
3、select count(1) from xxxx
默认查询,如果是多分片,这个结果会返回多条记录,每天记录是单一个分片的执行结果。
如果需要Mycat合并结果集,需要修改server.xml 的属性 :
useOffHeapForMerge=0
另,如果schema设置了sqlMaxLimit,而物理库中结果记录远大于此值,那么你查询的结果会总是不超过sqlMaxLimit。这是一个BUG。
4、Mybatis的批量insert/update
如果你的系统有mybatis对于Oracle环境下进行批量的insert或者update,那么对不起。
Mycat 不能很好识别和解析begin ... insert.... end 语句。
5、调用存储过程
恩,你没看错,不支持CallableStatement方式调用存过。得换Mycat自己的写法,而且还有限制。
1// create or replace procedure p_test(return_result out varchar,--返回结果,如果没有费用返回空字符串 2 // err_code out number,--异常编码 3 // err_msg out varchar,--异常消息 4 // p_order_item_id in varchar, --订单标识 5 // p_prod_offer_id in number 6 // ) as 7 // begin 8 // err_code:='0'; 9 // err_msg:=''; 10 // 11 // return_result:=0; 12 // 13 // exception 14 // when dup_val_on_index then 15 // err_code:= sqlcode; 16 // err_msg:=sqlerrm; 17 // when others then 18 // err_code:=sqlcode; 19 // err_msg:=sqlerrm; 20 // end p_test; 21 22 String sql = 23 "/*#mycat: sql=SELECT 1 FROM customer_order where cust_id='90000000000' */set @p_order_item_id='',@p_prod_offer_id=0; call p_test (@return_result,@err_code,@err_msg,@p_order_item_id,@p_prod_offer_id);select @return_result,@err_code,@err_msg"; 24 25 ps = conn.prepareStatement(sql); 26 ps.executeUpdate(); 27 rs = ps.getResultSet(); 28 if (rs != null) { 29 while (rs.next()) { 30 String returnVal = rs.getString(1); 31 Integer returnVal2 = rs.getInt(2); 32 String returnVal3= rs.getString(3); 33 System.out.println(returnVal); 34 System.out.println(returnVal2); 35 System.out.println(returnVal3); 36 } 37 }
6、分页排序有问题
如果你的数据足够多,你会发现oracle环境下采用rownum分页排序查询的结果,会同一页的结果每一次都可能不一样。
这是因为Mycat内部结果集合并逻辑的原因。需要换成limit形式。
7、内存飙升导致假死问题
嗯。这个是在1.6.5增加子查询后衍生的重大故障BUG。
采用单元测试 MycatSchemaStatVisitorTest.test5()
测试8层以上嵌套的sql,在本案例没提交前,发现mycat单机内存急剧飙升到700MB。
子查询达到14万之多。修正子查询逻辑后,条件组合仍达到33万之多。太恐怖了。
更详细请参见我的Pull requests:
https://github.com/MyCATApache/Mycat-Server/pull/1722
8、感言
Mycat是一个优秀的数据库分库分表中间件,但也正如其标榜和隐喻的,它很好地为MySQL为工作。
如果你需要Oracle分库分表,那么需要做大量的SQL检测,及相应的性能测试,才能启用Mycat。
by 斯武丶风晴 https://my.oschina.net/langxSpirit