Mycat适配oracle,各种坑

Stella981
• 阅读 910

注:文中使用版本为Mycat 1.6.5。

1、Mycat

正如官方所说,

Mycat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务。由于前面讲的对数据进行分片处理之后,从原有的一个库,被切分为多个分片数据库,所有的分片数据库集群构成了整个完整的数据库存储。

当然,Mycat没有自己的存储引擎,并不是完全意义的分布式数据库系统。

 以下是官方的架构图。

Mycat适配oracle,各种坑

我们可以清晰地看到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自己的写法,而且还有限制。

// create or replace procedure p_test(return_result out varchar,--返回结果,如果没有费用返回空字符串
      // err_code out number,--异常编码
      // err_msg out varchar,--异常消息
      // p_order_item_id in varchar, --订单标识
      // p_prod_offer_id in number
      // ) as
      // begin
      // err_code:='0';
      // err_msg:='';
      //
      // return_result:=0;
      //
      // exception
      // when dup_val_on_index then
      // err_code:= sqlcode;
      // err_msg:=sqlerrm;
      // when others then
      // err_code:=sqlcode;
      // err_msg:=sqlerrm;
      // end p_test;

      String sql =
          "/*#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";

      ps = conn.prepareStatement(sql);
      ps.executeUpdate(); 
      rs = ps.getResultSet();
      if (rs != null) {
        while (rs.next()) {
          String returnVal = rs.getString(1);
          Integer returnVal2 = rs.getInt(2);
          String returnVal3= rs.getString(3);
          System.out.println(returnVal);
          System.out.println(returnVal2);
          System.out.println(returnVal3);
        }
      }

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

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
待兔 待兔
4个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Java修道之路,问鼎巅峰,我辈代码修仙法力齐天
<center<fontcolor00FF7Fsize5face"黑体"代码尽头谁为峰,一见秃头道成空。</font<center<fontcolor00FF00size5face"黑体"编程修真路破折,一步一劫渡飞升。</font众所周知,编程修真有八大境界:1.Javase练气筑基2.数据库结丹3.web前端元婴4.Jav
Wesley13 Wesley13
3年前
RAC环境单实例启动数据库收到ORA
     在RAC环境中,如果你在没有启动节点的集群服务的情况下单实例启动数据库,将收到类似如下的报错:\oracle@rhel1u01\$sqlSQL\Plus:Release10.2.0.5.0ProductiononTueApr215:00:272013Copyright(
Stella981 Stella981
3年前
Python3:sqlalchemy对mysql数据库操作,非sql语句
Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''
Wesley13 Wesley13
3年前
MongoDB 分片管理(一)检查集群状态
一、检查集群状态1.1使用sh.status()查看集群摘要信息1、使用sh.status()可以查看分片信息、数据库信息、集合信息sh.status()如果数据块较多时,使用sh.status(true)又是输出会很多,就不会截断,要使用如下查看2、tooman
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Python进阶者 Python进阶者
10个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这