@@ -179,7 +179,9 @@ export PATH=$PATH:$MYCAT_HOME/bin
179179
180180 <!-- sharding-by-shop-id 为自己已定义的规则:根据店铺 ID 分库-->
181181 <!-- 父子表采用 ER 关系分片,规则是由上面的 adg_ads_campaign 表分片规则决定 -->
182- <!-- parentKey 为与父表建立关联关系的列名-->
182+ <!-- primaryKey 物理表中主键字段-->
183+ <!-- joinKey 物理表中关联父表字段-->
184+ <!-- parentKey 物理父表的主键字段-->
183185 <table name =" adg_ads_campaign" primaryKey =" ads_campaign_id" dataNode =" dn0,dn1,dn2" rule =" sharding-by-shop-id" >
184186 <childTable name =" adg_ads_set" primaryKey =" ads_set_id" joinKey =" shop_id" parentKey =" shop_id" >
185187 <childTable name =" adg_ads" joinKey =" ads_set_id" parentKey =" ads_set_id" />
@@ -594,6 +596,8 @@ INSERT INTO `adg_ads`(`ads_id`,`ads_set_id`,`ads_title`,`shop_id`,`channel_id`,
594596
595597## mycat 正常启动的 log 内容
596598
599+ - ` tail -300f wrapper.log `
600+
597601``` log
5986022018-02-05 14:15:41.432 INFO [WrapperSimpleAppMain] (io.mycat.backend.datasource.PhysicalDBPool.<init>(PhysicalDBPool.java:100)) - total resouces of dataHost mysql_host_0 is :1
5996032018-02-05 14:15:41.435 INFO [WrapperSimpleAppMain] (io.mycat.backend.datasource.PhysicalDBPool.<init>(PhysicalDBPool.java:100)) - total resouces of dataHost mysql_host_2 is :1
@@ -692,6 +696,151 @@ INSERT INTO `adg_ads`(`ads_id`,`ads_set_id`,`ads_title`,`shop_id`,`channel_id`,
692696 - 先编辑 /conf/schema.xml 文件,增加对应的表信息
693697 - 把创建表 SQL 放在虚拟库上执行,则各个节点的物理库表会增加对应的表结构
694698
699+ ------------------------------------------------------------------------------
700+
701+ ## 只垂直分库流程
702+
703+ - 垂直切分缺点
704+ - 如果不采用全局表那就只能通过 API 接口关联表数据(为了增加吞吐,可以考虑多线程并发执行 API 接口后整合)
705+ - 对于访问频繁、数据大的表,性能瓶颈依旧会存在
706+ - 这里只是写个大体思路,基础知识上面已经说了。
707+ - 假设以电商系统为例,拆分出:商品库、用户库、订单库,有 3 个 MySQL 实例各自存储一个业务库
708+ - 1 . 因为不进行水平切分,所以不需要修改 rule.xml
709+ - 2 . 修改 server.xml,增加用户和权限
710+ - 3 . 修改 schema.xml,增加逻辑库配置
711+ - dataHost 配置 3 个(只有 3 个 MySQL 实例)
712+ - dataNode 配置 3 个,分别对应:商品库(1 个)、用户库(1 个)、订单库(1 个)
713+ - schema 配置:
714+
715+ ```
716+ <schema name="adg_system" checkSQLschema="false" sqlMaxLimit="100">
717+
718+ <!--全局表 start-->
719+ <table name="adg_common" primaryKey="id" type="global" dataNode="dn0,dn1,dn2"/>
720+ <table name="adg_region" primaryKey="id" type="global" dataNode="dn0,dn1,dn2"/>
721+ <!--全局表 end-->
722+
723+ <!-- 分库表 start-->
724+ <table name="adg_product" primaryKey="id" dataNode="dn0"/>
725+ <table name="adg_sku" primaryKey="id" dataNode="dn0"/>
726+ <table name="adg_category" primaryKey="id" dataNode="dn0"/>
727+
728+ <table name="adg_user" primaryKey="id" dataNode="dn1"/>
729+ <table name="adg_role" primaryKey="id" dataNode="dn1"/>
730+
731+ <table name="adg_order" primaryKey="id" dataNode="dn2"/>
732+ <table name="adg_order_item" primaryKey="id" dataNode="dn2"/>
733+ <!-- 分库表 end-->
734+
735+ </schema>
736+ ```
737+
738+ ------------------------------------------------------------------------------
739+
740+ ## 垂直分库基础上进行水平切分
741+
742+ - 水平分片原则
743+ - 能不切分是最好的,能用归档方式分开存储,分开查询的尽可能通过产品思维层面解决
744+ - 一般只推荐那些数据量大,并且读写频繁的表进行切分
745+ - 选择合适的切分规则、分片键
746+ - 尽可能避免跨分片 JOIN 操作
747+ - 水平分片的步骤
748+ - 选择分片键和分片算法
749+ - 一般分片键推荐的是查询条件基本都会带上的那个字段,或者影响面很广的字段
750+ - 分片键是能尽可能均匀把数据分片到各个节点
751+ - 没有什么可以选择的时候,推荐就是主键
752+ - MyCAT 配置分片节点
753+ - 测试分片节点
754+ - 业务数据迁移
755+
756+ #### 对订单相关业务进行水平切分
757+
758+ - 一般选择订单号或者所属用户 ID 进行分片,这里推荐使用所属用户 ID,因为查询订单信息基本都是从用户角度发起的
759+ - 1 . 前面垂直分库已经修改 server.xml,这里不需要
760+ - 2 . 修改 rule.xml,修改分片规则
761+
762+ ```
763+ <tableRule name="sharding-by-user-id-to-order">
764+ <rule>
765+ <columns>user_id</columns>
766+ <algorithm>by-user-id-to-order</algorithm>
767+ </rule>
768+ </tableRule>
769+
770+ <function name="by-user-id-to-order" class="io.mycat.route.function.PartitionByMod">
771+ <!-- 订单只有 3 个物理库,所以这里填写 3 -->
772+ <property name="count">3</property>
773+ </function>
774+ ```
775+
776+ - 3 . 修改 schema.xml,增加逻辑库配置
777+ - dataHost 配置 3 个(只有 3 个 MySQL 实例)
778+ - dataNode 配置 5 个,分别对应:商品库(1 个)、用户库(1 个)、订单库(3 个)
779+ - schema 配置,这里使用取模分片算法:
780+
781+ ```
782+ <schema name="adg_system" checkSQLschema="false" sqlMaxLimit="100">
783+
784+ <!--全局表 start-->
785+ <table name="adg_common" primaryKey="id" type="global" dataNode="dn0,dn1,dn2"/>
786+ <table name="adg_region" primaryKey="id" type="global" dataNode="dn0,dn1,dn2"/>
787+ <!--全局表 end-->
788+
789+ <!-- 分库表 start-->
790+ <table name="adg_product" primaryKey="id" dataNode="dn0"/>
791+ <table name="adg_sku" primaryKey="id" dataNode="dn0"/>
792+ <table name="adg_category" primaryKey="id" dataNode="dn0"/>
793+
794+ <table name="adg_user" primaryKey="id" dataNode="dn1"/>
795+ <table name="adg_role" primaryKey="id" dataNode="dn1"/>
796+
797+ <table name="adg_order" primaryKey="id" dataNode="order_01,order_02,order_03" rule="sharding-by-user-id-to-order">
798+ <childTable name="adg_order_item" primaryKey="id" joinKey="order_id" parentKey="id"/>
799+ </table>
800+ <!-- 分库表 end-->
801+
802+ </schema>
803+ ```
804+
805+ ------------------------------------------------------------------------------
806+
807+ ## 其他常用配置
808+
809+ #### SQL 拦截(做审计,不分该 SQL 是否执行成功与否)
810+
811+ - 修改 server.xml(只拦截 UPDATE,DELETE,INSERT)
812+
813+ ```
814+ <property name="sqlInterceptor">io.mycat.server.interceptor.impl.StatisticsSqlInterceptor</property>
815+ <property name="sqlInterceptorType">UPDATE,DELETE,INSERT</property>
816+ <property name="sqlInterceptorFile">/opt/mycat-log.txt</property>
817+ ```
818+
819+ #### SQL 防火墙
820+
821+ - 作用
822+ - 限制某些用户只能通过某些主机访问(whitehost 标签)
823+ - 屏蔽一些 SQL 语句(blacklist 标签)
824+
825+ ```
826+ <firewall>
827+ <whitehost>
828+ <host user="adg_system_user" host="127.0.0.1"/>
829+ <host user="adg_system_user" host="127.0.0.2"/>
830+ </whitehost>
831+ <blacklist check="true">
832+ <!-- 不允许执行 delete 语句中不带 where 条件的 SQL -->
833+ <property name="deleteWhereNoneCheck">true</property>
834+ </blacklist>
835+ </firewall>
836+ ```
837+
838+
839+ ------------------------------------------------------------------------------
840+
841+
842+
843+
695844## 资料
696845
697846- 书:《分布式数据库架构及企业实践-基于 Mycat 中间件》
0 commit comments