@@ -179,7 +179,9 @@ export PATH=$PATH:$MYCAT_HOME/bin
179
179
180
180
<!-- sharding-by-shop-id 为自己已定义的规则:根据店铺 ID 分库-->
181
181
<!-- 父子表采用 ER 关系分片,规则是由上面的 adg_ads_campaign 表分片规则决定 -->
182
- <!-- parentKey 为与父表建立关联关系的列名-->
182
+ <!-- primaryKey 物理表中主键字段-->
183
+ <!-- joinKey 物理表中关联父表字段-->
184
+ <!-- parentKey 物理父表的主键字段-->
183
185
<table name =" adg_ads_campaign" primaryKey =" ads_campaign_id" dataNode =" dn0,dn1,dn2" rule =" sharding-by-shop-id" >
184
186
<childTable name =" adg_ads_set" primaryKey =" ads_set_id" joinKey =" shop_id" parentKey =" shop_id" >
185
187
<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`,
594
596
595
597
## mycat 正常启动的 log 内容
596
598
599
+ - ` tail -300f wrapper.log `
600
+
597
601
``` log
598
602
2018-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
599
603
2018-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`,
692
696
- 先编辑 /conf/schema.xml 文件,增加对应的表信息
693
697
- 把创建表 SQL 放在虚拟库上执行,则各个节点的物理库表会增加对应的表结构
694
698
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
+
695
844
## 资料
696
845
697
846
- 书:《分布式数据库架构及企业实践-基于 Mycat 中间件》
0 commit comments