MyCat踩坑记

作者: 始终我是我 | 来源:发表于2018-08-20 17:11 被阅读14次

    执行读取大量数据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进行优化。

    相关文章

      网友评论

        本文标题:MyCat踩坑记

        本文链接:https://www.haomeiwen.com/subject/kebliftx.html