数据库系列之MySQL基于Mycat的分库分表实现

MySQL分库分表可以通过中间件Mycat实现,本文简要介绍了Mycat的几种分片策略mode、range和hash,并分别进行测试验证


1、MySQL基于Mycat实现分库分表

1.1 分库分表原理

数据的切分(sharding)根据切分规则的类型,可以分为垂直切分和水平切分两种模式:

  • 垂直切分是按照不同的表切分到不同的数据库中,适用于业务系统之间耦合度低、业务逻辑清晰的系统
  • 水平切分是根据表中数据的逻辑关系,将同一个表中的数据按照某种条件拆分到多台数据库上,对应用来说更为复杂

分库分表根据垂直和水平切分分为四种:水平分库、水平分表、垂直分库、垂直分表。
数据库系列之MySQL基于Mycat的分库分表实现

  • MySQL垂直分区

MySQL垂直分区是在应用层将不同业务的数据放到不同的数据库服务器,当其中一个业务崩溃了也不会影响其他业务的正常进行,并且可以起到负载分流的作用,大大提升了数据库的吞吐能力。经过垂直分区后的数据库架构图如下:
数据库系列之MySQL基于Mycat的分库分表实现

垂直分区是通过不同业务进行分库,但是有些业务之间或多或少总会有点联系,而且这种分区不能解决单个业务数据量暴涨的问题。

  • MySQL水平分片(Sharding)

MySQL水平分片是将业务数据按照一定规则(如id哈希)分组,并把该组的数据存储到一个数据库分片中,这样随着用户数量的增加,只要简单地配置一台服务器即可,原理图如下:
数据库系列之MySQL基于Mycat的分库分表实现
分表分库虽然能解决大表对数据库系统的压力,但它并不是万能的,分库分表有以下原则:

  1. 1000 万以内的表,不建议分片,通过合适的索引,可以解决性能问题
  2. 分片数量尽量少,尽量均匀分布在多个 主机上,因为一个查询SQL跨分片越多,则总体性能越差
  3. 分片规则的选择,需要考虑数据的增长模式,数据的访问模式,分片关联性问题,以及分片扩容问题
  4. 尽量不要在一个事务中的 SQL 跨越多个分片
  5. 查询条件尽量优化,尽量避免“Select *”的方式,大量数据结果集下,会消耗大量带宽和 CPU 资源
1.2 Mycat实现分库分表

MyCAT通过定义表的分片规则来实现分片,分片规则中会定义分片字段和分片算法,分片算法包括hash、取模和范围分区等。每个表可以捆绑一个分片规则,每个分片规则指定一个分片字段并绑定一个函数,来实现动态分片算法 。
数据库系列之MySQL基于Mycat的分库分表实现

  1. Schema:逻辑库,与MySQL中的Database(数据库)对应,一个逻辑库中定义了所包括的Table。
  2. Table:逻辑表,即物理数据库中存储的某一张表,与传统数据库不同,这里的表需要声明其所存储的逻辑数据节点DataNode。在此可以指定表的分片规则。
  3. DataNode:MyCAT的逻辑数据节点,是存放table的具体物理节点,也称之为分片节点,通过DataSource来关联到后端某个具体数据库上
  4. Database:定义某个物理库的访问地址,用于捆绑到Datanode上
  5. 分片规则:前面讲了数据切分,一个大表被分成若干个分片表,就需要一定的规则,这样按照某种业务规则把数据分到某个分片的规则就是分片规则,数据切分选择合适的分片规则非常重要,将极大的避免后续数据处理的难度
1.2.1 环境准备

1)MySQL主从复制集群环境:参考“MySQL主从复制集群架构部署”

2)Mycat安装:参考“MySQL主从复制读写分离实现”

3)启动MySQL集群环境

[mysql@tango-centos01 mysql]$ service mysql start
[mysql@tango-centos01 mysql]$ service mysql status
1.2.2 MyCAT分库分表配置

Mycat中配置文件主要有schema.xml和rule.xml:schema.xml指定的是各个数据库节点与MyCat中虚拟数据库和表的关联关系,并且指定了当前表的分表策略;在rule.xml中则指定了具体的分表策略及其所使用的算法实现类。MyCAT中常用分片算法包括取模、范围分片和一致性hash算法,以下分别介绍三种算法配置。

1)取模

<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
  <!-- 指定了对外所展示的数据库名称,也就是说,客户端连接MyCat数据库时,制定的database为mydb
       而当前数据库中的表的配置就是根据下面的配置而来的 -->
  <schema name="mydb" checkSQLschema="true" sqlMaxLimit="100">
    <!-- 定义了一个t_goods表,该表的主键是id,该字段是自增长的,并且该表的数据会被分配到dn1,dn2和
         dn3上,这三个指的是当前MyCat数据库所代理的真实数据库的节点名,每个节点的具体配置在下面的
         配置中。这里rule属性指定了t_goods表中的数据分配到dn1,dn2和dn3上的策略,mod-long指的是
         按照长整型取余的方式分配,也就是按照id对节点数目进行取余 -->
    <table name="t_goods" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2,dn3" 
           rule="mod-long"/>
  </schema>

  <!-- 分别指定了dn1,dn2和dn3三个节点与对应的数据库的关系,dataHost对应的就是下面的数据库节点配置 -->
  <dataNode name="dn1" dataHost="dhost1" database="db1"/>
  <dataNode name="dn2" dataHost="dhost2" database="db2"/>
  <dataNode name="dn3" dataHost="dhost3" database="db3"/>

  <!-- 这里分别指定了各个数据库节点的配置 -->
  <dataHost name="dhost1" maxCon="1000" minCon="10" balance="0" writeType="0" 
            dbType="mysql" dbDriver="native">
    <heartbeat>select user()</heartbeat>
    <writeHost host="hostM1" url="localhost:3306" user="root" password="password"/>
  </dataHost>
a
  <dataHost name="dhost2" maxCon="1000" minCon="10" balance="0" writeType="0" 
            dbType="mysql" dbDriver="native">
    <heartbeat>select user()</heartbeat>
    <writeHost host="hostM2" url="localhost:3306" user="root" password="password"/>
  </dataHost>

  <dataHost name="dhost3" maxCon="1000" minCon="10" balance="0" writeType="0" 
            dbType="mysql" dbDriver="native">
    <heartbeat>select user()</heartbeat>
    <writeHost host="hostM3" url="localhost:3306" user="root" password="password"/>
  </dataHost>
</mycat:schema>

rules.xml配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
  <!-- 这里的mod-long对应的就是上面schema.xml的表配置中rule属性所使用的规则名称,其columns节点
       指定了当前规则所对应的字段名,也就是id,algorithm节点则指定了当前规则所使用的算法,具体的
       算法对应于下面的function节点所指定的实现类-->
	<tableRule name="mod-long">
		<rule>
			<columns>id</columns>
			<algorithm>mod-long</algorithm>
		</rule>
	</tableRule>
  
  <!-- 这里指定的是mod-long这个算法所使用的具体实现类,实现类需要使用全限定路径,具体的代码读者朋友
       可以阅读MyCat源码,并且读者也可以查看MyCat默认为我们提供了哪些分表策略实现 -->
	<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
		<!-- 指定了当前所使用的数据库节点数 -->
		<property name="count">3</property>
	</function>
</mycat:rule>

2)按范围分片

按照范围分片,顾名思义,就是首先对整体数据进行范围划分,然后将各个范围区间分配到对应的数据库节点上,当用户插入数据时,根据指定字段的值,判断其属于哪个范围,然后将数据插入到该范围对应的数据库节点上。

<!-- schema.xml -->
<table name="t_company" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="range-sharding-by-id-count"/>

rules.xml配置如下:

<!-- rule.xml -->
<tableRule name="range-sharding-by-id-count">
  <rule>
    <!-- 指定了分片字段 -->
    <columns>id</columns>
    <algorithm>range-id-count</algorithm>
  </rule>
</tableRule>

<function name="range-id-count" class="io.mycat.route.function.AutoPartitionByLong">
  <!-- 指定了范围分片的”范围-节点“的对应策略 -->
  <property name="mapFile">files/tb-range-partition.txt</property>
  <!-- 指定了超出范围的数据将会被分配的数据节点 -->
  <property name="defaultNode">0</property>
</function>

其中mapFile指定范围和数据节点的对应关系,如下:

<!-- 上面mapFile属性指定的id-range-partition.txt文件内容,这里指定了具体的范围与数据节点的对应关系 -->
0-10=0
11-50=1
51-100=2
101-1000=0
1001-9999=1
10000-9999999=2

3)一致性Hash分片

<!-- schema.xml -->
<table name="t_house" primaryKey="id" autoIncrement="true" dataNode="dn1,dn2,dn3" rule="sharding-by-hash"/>

rule.xml文件如下:

<!-- rule.xml -->
<tableRule name="sharding-by-murmur">
  <rule>
    <columns>id</columns>
    <algorithm>hash</algorithm>
  </rule>
</tableRule>

<!-- 下面的属性中,count指定了要分片的数据库节点数量,必须指定,否则没法分片;virtualBucketTimes指的是
     一个实际的数据库节点被映射为这么多虚拟节点,默认是160倍,也就是虚拟节点数是物理节点数的160倍;
     weightMapFile指定了节点的权重,没有指定权重的节点默认是1。以properties文件的格式填写,
     以从0开始到count-1的整数值也就是节点索引为key,以节点权重值为值。所有权重值必须是正整数,
     否则以1代替;bucketMapPath用于测试时观察各物理节点与虚拟节点的分布情况,如果指定了这个属性,
     会把虚拟节点的murmur hash值与物理节点的映射按行输出到这个文件,没有默认值,如果不指定,
     就不会输出任何东西-->
<function name="hash" class="io.mycat.route.function.PartitionByMurmurHash">
		<property name="seed">0</property><!-- 默认是0 -->
		<property name="count">3</property>
		<property name="virtualBucketTimes">160</property><!--  -->
		<!-- <property name="weightMapFile">weightMapFile</property> -->
		<property name="bucketMapPath">
      /usr/local/mycat/bucketMap.txt</property>
	</function>
1.2.3 MyCAT分库分表测试

MyCat分库分表测试场景如下:
数据库系列之MySQL基于Mycat的分库分表实现
1)创建数据库和表

在主机192.168.112.101的mysql上创建数据库TESTDB01和TESTDB02,在192.168.112.102和192.168.112.103上分别创建数据库TESTDB03和TESTDB04。需要将表TB01放在库TESTDB01和TESTDB02中,表TB02分表放到库TESTDB02、TESTDB03和TESTDB04中,表TB03放到TESTDB03和TESTDB04中。

  • 在192.168.112.101节点
[mysql@tango-centos01 mysql]$ ./bin/mysql -uroot –ppassword
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 10
Server version: 5.7.31-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
mysql> CREATE DATABASE TESTDB01 CHARACTER SET utf8 COLLATE utf8_general_ci; 
Query OK, 1 row affected (0.89 sec)

mysql> use TESTDB01;
Database changed
mysql> create table TB01 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.36 sec)

mysql> CREATE DATABASE TESTDB02 CHARACTER SET utf8 COLLATE utf8_general_ci;  
Query OK, 1 row affected (0.00 sec)

mysql> use TESTDB02;
Database changed
mysql> create table TB01 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.22 sec)

mysql> create table TB02 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)
  • 在192.168.112.102节点
[mysql@tango-centos02 mysql]$ ./bin/mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 41
Server version: 5.7.31-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE TESTDB03 CHARACTER SET utf8 COLLATE utf8_general_ci; 
Query OK, 1 row affected (0.11 sec)

mysql> use TESTDB03;
Database changed
mysql> create table TB02 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.29 sec)

mysql> create table TB03 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

  • 在192.168.112.103节点
[mysql@tango-centos03 mysql]$ ./bin/mysql -uroot -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 47
Server version: 5.7.31-log MySQL Community Server (GPL)

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> CREATE DATABASE TESTDB04 CHARACTER SET utf8 COLLATE utf8_general_ci; 
Query OK, 1 row affected (0.11 sec)

mysql> use TESTDB04;
Database changed
mysql> create table TB02 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.05 sec)

mysql> create table TB03 (id int not null auto_increment,city varchar(50) not null, primary key(id)) AUTO_INCREMENT= 1 ENGINE=InnoDB DEFAULT CHARSET=utf8;
Query OK, 0 rows affected (0.01 sec)

特别需要注意的是:

  • 分表的表在创建时一定要创建主键,否则在mycat端写入数据时会报错主键冲突
  • 分表的表要在跨库的几个库上都要创建。

2)配置MyCAT

登录mycat机器192.168.112.10机器,分别设置server.xml文件、rule.xml文件、schema.xml文件

  • server.xml配置
[root@tango-01 mycat]## vim conf/server.xml
......
<!-- mycat的服务端口默认为8066,管理端口默认为9066 -->
         <property name="serverPort">8066</property> <property name="managerPort">9066</property>
.....
<!-- 任意设置登陆 mycat 的用户名,密码,数据库  -->
        <user name="root">
                <property name="password">password</property>
                <property name="schemas">mycat</property>
.....
 </mycat:server>
  • 配置Rules文件

分库分表配置涉及到rule.xml文件,本次测试过程中分别验证取模、范围和一致性hash三种分片算法,配置如下:

[root@tango-01 conf]# cp rule.xml rule.xml.bak
[root@tango-01 conf]# vim rule.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- - - Licensed under the Apache License, Version 2.0 (the "License");
    - you may not use this file except in compliance with the License. - You
    may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0
    - - Unless required by applicable law or agreed to in writing, software -
    distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT
    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the
    License for the specific language governing permissions and - limitations
    under the License. -->
<!DOCTYPE mycat:rule SYSTEM "rule.dtd">
<mycat:rule xmlns:mycat="http://io.mycat/">
  
    <tableRule name="mod-rule">                <!—TB01表分片的规则名,这里定义为取模分区mod-rule,这个需要在schema.xml文件中引用 -->
        <rule>
            <columns>id</columns>                  <!—TB01表的分片列 -->
            <algorithm>mod-long</algorithm>
        </rule>
</tableRule>

      <tableRule name="range-rule">                <!—TB02表分片的规则名,这里定义为范围分区range-rule,这个需要在schema.xml文件中引用 -->
        <rule>
            <columns>id</columns>                  <!—TB02表的分片列 -->
            <algorithm>range-id-count</algorithm>
        </rule>
    </tableRule>

      <tableRule name="hash-rule">                <!—TB03表分片的规则名,这里定义为范围分区range-rule,这个需要在schema.xml文件中引用 -->
        <rule>
            <columns>id</columns>                  <!—TB02表的分片列 -->
            <algorithm>hash-murmur</algorithm>
        </rule>
    </tableRule>

<!—TB01表分配到TESTDB01和TESTDB02库中 -->
    <function name="mod-long" class="io.mycat.route.function.PartitionByMod">
        <!-- how many data nodes -->
        <property name="count">2</property>        <!-- count值与分片个数相同,这里TB01表分片到TESTDB01库和TESTDB02库里,共2份。 -->
</function>

<!—TB02表分配到TESTDB02、TESTDB03和TESTDB04库中 -->
<function name="range-id-count" class="io.mycat.route.function.AutoPartitionByLong">
  <!-- 指定了范围分片的”范围-节点“的对应策略 -->
  <property name="mapFile">files/tb02-range-partition.txt</property>
  <!-- 指定了超出范围的数据将会被分配的数据节点 -->
  <property name="defaultNode">0</property>
</function>

<!—TB03表分配到TESTDB03和TESTDB04库中 -->
<function name="hash-murmur" class="io.mycat.route.function.PartitionByMurmurHash">
		<property name="seed">0</property><!-- 默认是0 -->
		<property name="count">2</property>
		<property name="virtualBucketTimes">160</property><!--  -->
		<property name="bucketMapPath">/usr/local/mycat/tb03-bucketMap.txt</property>
	</function>

</mycat:rule>

创建文件files/tb02-range-partition.txt

0-10=0
11-50=1
51-100=2
101-1000=0
1001-9999=1
10000-9999999=2
  • 配置schema.xml文件
[root@tango-01 conf]# cp schema.xml schema.xml.old
[root@tango-01 conf]# vim schema.xml
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">


    <schema name="mycat" checkSQLschema="false" sqlMaxLimit="100">
        <table name="TB01" primaryKey="id"  dataNode=" DN01,DN02" rule="mod-rule" />
        <table name="TB02" primaryKey="id"  dataNode=" DN02,DN03,DN04" rule="range-rule" />
        <table name="TB03" primaryKey="id"  dataNode="DN03,DN04" rule="hash-rule" />
    </schema>
    
    <dataNode name="DN01" dataHost="DH01" database=" TESTDB01" />
    <dataNode name="DN02" dataHost="DH01" database=" TESTDB02" />
    <dataNode name="DN03" dataHost="DH02" database=" TESTDB03" />
    <dataNode name="DN04" dataHost="DH03" database=" TESTDB04" />

    <dataHost name="DH01" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user()</heartbeat>
        <writeHost host="192.168.112.101" url="192.168.112.101:3306" user="root" password="password">
        </writeHost>
    </dataHost>
    <dataHost name="DH02" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" >
        <heartbeat>select user()</heartbeat>
        <writeHost host="192.168.112.102" url="192.168.112.102:3306" user="root" password="password">
        </writeHost>
    </dataHost>
    <dataHost name="DH03" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native">
        <heartbeat>select user()</heartbeat>
        <writeHost host="192.168.112.103" url="192.168.112.103:3306" user="root" password="password">
        </writeHost>
    </dataHost>

</mycat:schema>

4)启动Mycat服务

[root@tango-01 mycat]# ./bin/mycat start
Starting Mycat-server...
[root@tango-01 mycat]# ./bin/mycat status
Mycat-server is running (9348).
[root@tango-01 mycat]# lsof -i:8066
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    9350 root   81u  IPv6 215883      0t0  TCP *:8066 (LISTEN)
[root@tango-01 mycat]# lsof -i:9066
COMMAND  PID USER   FD   TYPE DEVICE SIZE/OFF NODE NAME
java    9350 root   77u  IPv6 215878      0t0  TCP *:9066 (LISTEN)

5)在客户机远程登录Mycat

[root@tango-01 mysql]# ./bin/mysql -h192.168.112.10 -P8066 -uroot -ppassword
Warning: Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.6.29-mycat-1.6.7.1-release-20200209222254 MyCat Server (OpenCloudDB)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
mysql> show databases;
+----------+
| DATABASE |
+----------+
| mycat    |
+----------+
1 row in set (0.00 sec)

mysql> use mycat
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables in mycat |
+-----------------+
| tb01            |
| tb02            |
| tb03            |
+-----------------+
3 rows in set (0.00 sec)

mysql> select * from TB01;
Empty set (0.14 sec)

mysql> select * from TB02;
Empty set (0.58 sec)

mysql> select * from TB03;
Empty set (0.04 sec)

6)验证Mod分片策略

  • 在mycat里往TB01
mysql> insert into TB01(id,city) values(1,"Anhui");
Query OK, 1 row affected (0.06 sec)

mysql> insert into TB01(id,city) values(2,"Beijing");
Query OK, 1 row affected (0.00 sec)

mysql> insert into TB01(id,city) values(11,"Guangzhou");
Query OK, 1 row affected (0.00 sec)

mysql> insert into TB01(id,city) values(21,"Shenzhen");
Query OK, 1 row affected (0.01 sec)

特别注意:在配置了sharding分片策略之后(如heihei表),mycat里分片的表做插入数据时,即使插入所有字段的数据,也一定要在表名后面写明插入数据的字段名称,否则插入数据会报错:ERROR 1064 (HY000): partition table, insert must provide ColumnList

  • 登录192.168.112.101服务器,查看从mycat端写入的数据
mysql> use TESTDB01;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------+
| Tables_in_TESTDB01 |
+--------------------+
| TB01               |
+--------------------+
1 row in set (0.00 sec)

mysql> select * from TB01;
+----+---------+
| id | city    |
+----+---------+
|  2 | Beijing |
+----+---------+
1 row in set (0.03 sec)

mysql> use TESTDB02;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------+
| Tables_in_TESTDB02 |
+--------------------+
| TB01               |
| TB02               |
+--------------------+
2 rows in set (0.00 sec)

mysql> select * from TB01;
+----+-----------+
| id | city      |
+----+-----------+
|  1 | Anhui     |
| 11 | Guangzhou |
| 21 | Shenzhen  |
+----+-----------+
3 rows in set (0.00 sec)

7)验证范围分片策略

  • 在mycat里往TB02插入数据
mysql> insert into TB02(id,city) values(1,"Anhui");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB02(id,city) values(2,"Beijing");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB02(id,city) values(11,"Guangzhou");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB02(id,city) values(21,"Shenzhen");
Query OK, 1 row affected (0.02 sec)

mysql> insert into TB02(id,city) values(61,"Chengdu");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB02(id,city) values(132,"Hangzhou");
Query OK, 1 row affected (0.00 sec)

mysql> select * from TB02;
+-----+-----------+
| id  | city      |
+-----+-----------+
|   1 | Anhui     |
|   2 | Beijing   |
| 132 | Hangzhou  |
|  11 | Guangzhou |
|  21 | Shenzhen  |
|  61 | Chengdu   |
+-----+-----------+
6 rows in set (0.02 sec)
  • 登录192.168.112.101-103服务器,查看从mycat端写入的数据
mysql> use TESTDB02;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+--------------------+
| Tables_in_TESTDB02 |
+--------------------+
| TB01               |
| TB02               |
+--------------------+
2 rows in set (0.00 sec)

mysql> select * from TB02;
+-----+----------+
| id  | city     |
+-----+----------+
|   1 | Anhui    |
|   2 | Beijing  |
| 132 | Hangzhou |
+-----+----------+
3 rows in set (0.00 sec)

mysql> use TESTDB03;
Database changed
mysql> show tables;
+--------------------+
| Tables_in_TESTDB03 |
+--------------------+
| TB02               |
| TB03               |
+--------------------+
2 rows in set (0.00 sec)

mysql> select * from TB02;
+----+-----------+
| id | city      |
+----+-----------+
| 11 | Guangzhou |
| 21 | Shenzhen  |
+----+-----------+
2 rows in set (0.00 sec)

mysql> use TESTDB04;
Database changed
mysql> show tables;
+--------------------+
| Tables_in_TESTDB04 |
+--------------------+
| TB02               |
| TB03               |
+--------------------+
2 rows in set (0.00 sec)

mysql> select * from TB02;
+----+---------+
| id | city    |
+----+---------+
| 61 | Chengdu |
+----+---------+
1 row in set (0.00 sec)

8)验证Hash分片策略

  • 在mycat里往TB03插入数据
mysql> insert into TB03(id,city) values(1,"Anhui");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB03(id,city) values(2,"Beijing");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB03(id,city) values(11,"Guangzhou");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB03(id,city) values(21,"Shenzhen");
Query OK, 1 row affected (0.02 sec)

mysql> insert into TB03(id,city) values(61,"Chengdu");
Query OK, 1 row affected (0.01 sec)

mysql> insert into TB03(id,city) values(132,"Hangzhou");
Query OK, 1 row affected (0.00 sec)

mysql> select * from TB03;
+-----+-----------+
| id  | city      |
+-----+-----------+
|   1 | Anhui     |
|   2 | Beijing   |
| 132 | Hangzhou  |
|  11 | Guangzhou |
|  21 | Shenzhen  |
|  61 | Chengdu   |
+-----+-----------+
6 rows in set (0.02 sec)
  • 登录192.168.112.102-103服务器,查看从mycat端写入的数据
mysql> select * from TESTDB03.TB03;
+----+----------+
| id | city     |
+----+----------+
| 21 | Shenzhen |
+----+----------+
1 row in set (0.00 sec)

mysql> select * from TESTDB04.TB03;
+-----+-----------+
| id  | city      |
+-----+-----------+
|   1 | Anhui     |
|   2 | Beijing   |
|  11 | Guangzhou |
|  61 | Chengdu   |
| 132 | Hangzhou  |
+-----+-----------+
5 rows in set (0.00 sec)

从上面可以看出,TB01、TB02和TB03使用mycat中的mod、range和hash三种分片策略,成功实现了分库分表功能。


参考资料

  1. http://mycat.org.cn/document/mycat-definitive-guide.pdf
  2. https://www.cnblogs.com/kevingrace/p/9365840.html
  3. https://www.cnblogs.com/littlecharacter/p/9342129.html
  4. https://www.jianshu.com/p/c6e29d724fca
  5. https://my.oschina.net/ydsakyclguozi/blog/199498
  6. https://my.oschina.net/zhangxufeng/blog/3097533

转载请注明原文地址:https://blog.csdn.net/solihawk/article/details/117837927
文章会同步在公众号“牧羊人的方向”更新,感兴趣的可以关注公众号,谢谢!
数据库系列之MySQL基于Mycat的分库分表实现

上一篇:删除数据


下一篇:旅行商问题的近似算法之最近邻法(Nearest Neighbor) C语言实现