MyCat踩坑记

执行读取大量数据SQL执行一段时间就不执行了?

​ MyCat的默认SQL执行超时时间是300S(5分钟),需要调整MyCat的配置文件server.xml的配置。

    <system>
        <!--sql超时,单位秒-->
        <property name="sqlExecuteTimeout">1800</property>      
    </system>

ER分片子表的路由规则

一、如果子表与父表的关联字段是父表的分片字段

<!--使用orders表的主键user_id进行分片-->
<table name="orders" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" >
            <!-- 关联分片字段 -->
             <childTable name="order_items" primaryKey="order_items_id" joinKey="order_id" parentKey="order_id" /> 
        </table>
  • 在对子表进行update时(根据主键),会向所有节点发送sql语句。
  • 字表的分片规则则按照父表进行分片
  • 查询字表时,如果根据字表的主键来查,会被路由到所有节点(此时应该保证子表在所有分片是主键唯一的)
  • 如果根据父节点的分片字段(joinKey)来进行查询,会根据父表的路由规则进行查询。字表与父表进行join查询时也会走父表的路由。

二、当子表与父表的关联字段不是父表的分片字段时,

<!--根据orders表的地域编码area_code来分片-->
        <table name="orders" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" >
            <!-- 关联非分片字段 -->
             <childTable name="user_items" primaryKey="user_iterm_id" joinKey="order_id" parentKey="order_id" /> 

        </table>
  • 子表的分片规则是根据父表的parentKey所在的分片区域进行分片。
  • 对字表进行update语句(通过主键ID或者parentKey)时会向所有节点发送sql,因为无法确定父节点的分片信息。
  • 必须通过查找对应的父表记录来确认子表所在分片,如果找不到则会抛出错误,在join查询的时候,路由走的是所有分片节点。
  • 非主键的分片,MyCAT 提供了“主键到分片”的内存缓存机制,热点数据按照主键查询,丝毫不损失性能。

MyCat数据导入与导出

一、导出

​ 导出分片数据最好是到每个分片节点去导出,然后进行合并,避免数据冲突。

二、导入

​ 导入大量的分片数据可以使用 select * from table into outfile 命令从需要备份的mysql数据库导出数据。然后用命令行工具连接到MyCat,并执行 “load data infile ` 命令来导入分片数据。

多对多关联关系

​ 业务中往往存在多对多的关联关系,比如:商户会员+订单+商户,这时分片的策略往往是根据业务需求、性能差异来决定的(多表join)。如果需要获取会员所有的商户订单,并且依赖会员表的业务关系较多这时就可以考虑使用会员表分片。反之则相反。

ER分片子表update操作

​ ER分片,对childTabe进行update时、不能更新joinKey ,会报:Parent relevant column cant’t be update …….。很多框架更新默认都会根据主键更新所有字段,可以说这是很坑的地方,需要对sql进行重写。。

非主键分片性能优化

对于某些场景下,可能分片的字段不是主键。主键分片也并非是唯一的选择。

  • 该业务字段是最频繁的或者最重要的查询条件。

  • 将数据尽可能均匀分布的各个节点

    <!--配置了primaryKey 会缓存非主键分片的映射-->
          <table name="orders" primaryKey="order_id" dataNode="dn1,dn2" rule="mod-long" needAddLimit="false" >
              
              <!-- 关联非分片字段 -->
               <childTable name="user_items" primaryKey="user_iterm_id" joinKey="order_id" parentKey="order_id" /> 
    
          </table>
    

这种情况下MyCAT 提供了“主键到分片”的内存缓存机制,热点数据按照主键查询,不用担心牺牲了主键查询的性能。

对于非主键分片的 table,填写属性 primaryKey,此时 MyCAT 会将你根据主键查询的 SQL 语句的第一次执 行结果进行分析,确定该 Table 的某个主键在什么分片上,并进行主键到分片 ID 的缓存。第二次或后续查询 mycat 会优先从缓存中查询是否有 id–>node 即主键到分片的映射,如果有直接查询,通过此种方法提高了非主 键分片的查询性能。

MyCat建表和存储过程

MyCat建表需要使用注解语法,如 select 1 from table查出来的数据在那个节点往哪个节点执行

创建存储过程

/*!mycat: sql=select 1 from 表 */ CREATE DEFINER=root@% PROCEDURE proc_test() BEGIN END ;

建表

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

MyCat性能监控工具——MyCat-Web

MyCat官方提供的性能监控工具,可以对sql进行监控、查询统计、执行时间监控。可以根据监控结果对程序或者配置进行一系列的调整。

点这里下载MyCat-Web,使用方法见解压后的readme.txt。

MyCat快速体验,MyCat官方已经制作好了镜像,集成了一套测试环境,安装VirtualBox导入即可快速体验。

MyCat拆分原则(转自MyCat权威指南)

  1. 达到一定数量级才拆分(800 万)

  2. 不到 800 万但跟大表(超 800 万的表)有关联查询的表也要拆分,在此称为大表关联表

  3. 大表关联表如何拆:小于 100 万的使用全局表;大于 100 万小于 800 万跟大表使用同样的拆分策略;无 法跟大表使用相同规则的,可以考虑从 java 代码上分步骤查询,不用关联查询,或者破例使用全局表。

  4. 破例的全局表:如 item_sku 表 250 万,跟大表关联了,又无法跟大表使用相同拆分策略,也做成了全局 表。破例的全局表必须满足的条件:没有太激烈的并发 update,如多线程同时 update 同一条 id=1 的记录。虽 有多线程 update,但不是操作同一行记录的不在此列。多线程 update 全局表的同一行记录会死锁。批量 insert 没问题。

  5. 拆分字段是不可修改的。

  6. 拆分字段只能是一个字段,如果想按照两个字段拆分,必须新建一个冗余字段,冗余字段的值使用两个字 段的值拼接而成(如大区+年月拼成 zone_yyyymm 字段)。

  7. 拆分算法的选择和合理性评判:按照选定的算法拆分后每个库中单表不得超过 800 万

  8. 能不拆的就尽量不拆。如果某个表不跟其他表关联查询,数据量又少,直接不拆分,使用单库即可。

开发框架的选择

由于MyCat的兼容性、不能更新分片字段等限制。不建议使用Hibernate框架开发,最好的选择是能控制SQL的框架,比如MyBatisJDBC,可以针对SQL进行优化。

    原文作者:始终我是我
    原文地址: https://www.jianshu.com/p/7a8f8316d440
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞