vlambda博客
学习文章列表

MyCat 介绍及分表测试

MyCat 介绍及分表测试

  • 官方 http://www.mycat.org.cn/

  • github https://github.com/MyCATApache/Mycat-Server

1.简介

1.1 什么是MYCAT

MyCat 是流行的基于 java 语言编写的数据库中间件,是一个实现了 MySQL 协议的服务器,前端用户可以把它看作是一个数据库代理,用 MySQL 客户端工具和命令行访问,而其后端可以用 MySQL 原生协议与多个 MySQL 服务器通信,也可以用 JDBC 协议与大多数主流数据库服务器通信,其核心功能是分库分表。配合数据库的主从模式还可实现读写分离。

MyCat 是数据库中间件,就是介于数据库与应用之间,进行数据处理与交互的中间服务。MyCat是代理,MyCat后面就是物理数据库。和Web服务器的 Nginx类似。对于使用者来说,访问的都是 MyCat,不会接触到后端的数据库。

MyCat特性:

 
   
   
 
  1. - 支持SQL92标准

  2. - 支持MySQLOracleDB2SQL ServerPostgreSQLDB的常见SQL语法

  3. - 遵守Mysql原生协议,跨语言,跨平台,跨数据库的通用中间件代理。

  4. - 基于心跳的自动故障切换,支持读写分离,支持MySQL主从,以及galera cluste

  5. - 支持Galera for MySQL集群,Percona Cluster或者MariaDB cluster

  6. - 基于Nio实现,有效管理线程,解决高并发问题。

  7. - 支持数据的多片自动路由与聚合,支持sum,count,max等常用的聚合函数,支持跨库分页。

  8. - 支持单库内部任意join,支持跨库2join,甚至基于caltlet的多表join

  9. - 支持通过全局表,ER关系的分片策略,实现了高效的多表join查询。

1.2 MYCAT架构

1.3 名词概念

名词 说明
逻辑库 (schema) 数据库中间件可以被看做是一个或多个数据库集群构成的逻辑库
逻辑表(table) 分布式数据库中,对应用来说,读写数据的表就是逻辑表。
分片表 每个分片都有一部分数据,所 有分片构成了完整的数据. eg
非分片表 非分片是相对分片表来说的,就是那 些不需要进行数据切分的表,eg.
数据主机 dataHost 主机地址.可以使用主机名,IP,域名定义.
分片节点(dataNode) 一个大表被分到不同的分片数据库上面,每个表分片所在的数据库就是分片节点 (dataNode )
分片规则(rule) 1个大表被分成若干个分片表,需要的规则
多租户 多用户的环境下共用相同的系统或程序组件,并且仍可确保各用户间数据的隔离性。
ER 表 ER表示(Entity-Relationship Model)描述了真实世界中事物与关系。mycat子表与父表记录存放在同一个数据分片上,避免跨库join。
全局表 类似字典表的表

2. 环境规划

IP Port DB角色 MyCat
192.124.64.214 - - MyCat
192.124.64.212 3307 DB1 master -
192.124.64.213 3307 DB2 slave -

3.安装布署

3.1 MySQL安装

从库同步:

 
   
   
 
  1. DB1做为主,DB2,DB3为从库

  2. #授权

  3. grant replication client,replication slave on *.* to 'repl'@'10.%' IDENTIFIED BY 'repl123';


  4. #DB2,DB3建立主从关系

  5. CHANGE MASTER TO

  6. MASTER_HOST='192.124.64.212',

  7. MASTER_PORT=3307,

  8. MASTER_USER='repl',

  9. MASTER_PASSWORD='repl123',

  10. MASTER_AUTO_POSITION = 1;

  11. #

  12. start slave ;

  13. show slave status\G

授权Mycat账号:

 
   
   
 
  1. grant all privileges on *.* to mycat@'10.%' identified by 'mycat123';

  2. grant all on *.* to 'mycat_r'@'10.%' identified by 'mycat123';

3.2 MyCat软件安装

Mycat 需要先安装Java,然后在 http://www.mycat.org.cn/ 下载软件,解压缩即完成安装。当前版本为 Mycat-server-1.6.7.4。

  • 下载软件

  • 解压软件

  • 配置profile

 
   
   
 
  1. #安装java 略


  2. #下载软件

  3. $wget 'http://dl.mycat.io/1.6.7.4/Mycat-server-1.6.7.4-release/Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz' .


  4. #解压,建议路径/usr/local/mycat

  5. $tar -zxvf Mycat-server-1.6.7.4-release-20200105164103-linux.tar.gz

  6. $mv mycat /usr/local/

  7. #创建mycat用户

  8. useradd mycat

  9. chown -R mycat:mycat /usr/local/mycat


  10. $vim /etc/profile

  11. #JAVA_HOME=/usr/local/jdk

  12. JAVA_HOME=/usr/java/jdk1.8.0_101

  13. CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar

  14. PATH=$JAVA_HOME/bin:$PATH

  15. export JAVA_HOME

  16. #M

  17. MYCAT_HOME=/usr/local/mycat

  18. source /etc/profile

MyCat目录介绍:

 
   
   
 
  1. $tree /usr/local/mycat -L 1

  2. /usr/local/mycat

  3. ├── bin # bin 目录里是启动脚本

  4. ├── catlet # conf 目录里是配置文件

  5. ├── conf # catlet 为 Mycat 的一个扩展功能

  6. ├── lib # lib 目录里是 Mycat 和它的依赖 jar

  7. ├── logs # logs 目录里是 console.log 用来保存控制台日志,

  8. └── version.txt # 版本

启动/停止:

 
   
   
 
  1. $su - mycat

  2. $cd /usr/local/mycat/

  3. #启动:

  4. $./mycat start

  5. $./mycat stop


  6. #mycat 支持的命令{ console | start | stop | restart | status | dump }

  7. $bin/mycat

  8. Usage: bin/mycat { console | start | stop | restart | status | dump }

4. MyCAT配置

MyCat是代理,MyCat后面是物理数据库。Mycat 的配置文件都在MYCAT_HOME/conf 目录里面,这里介绍几个常用的文件。若配置文件修改,需要重启 Mycat 或者通过 9066 端口 reload。

文件 说明
server.xml 定义用户以及系统相关变量,如端口等
schema.xml 定义逻辑库,表、分片节点等内容
rule.xml MyCat 分库分表规则

4.1 server.xml

server.xml可用来配置账号,参数及相关操作权限的文件。system标签中设置的是系统级别的相关参数,初始默认即可。user标签是我们要注意的地方。

Mycat 端口是在server.xml中设置。Mycat的默认端口号为:8066 , 管理端口: 9066 有些用户会把Mycat端口8066改为MySQL的3306端口,方便使用。

server.xml

  • xx   系统配置

  • 定义MyCAT的账号,用户用此账号访问MyCat。

示例:

 
   
   
 
  1. <mycat:server xmlns:mycat="http://io.mycat/">

  2. <system>

  3. <property name="nonePasswordLogin">0</property>

  4. <property name="ignoreUnknownCommand">1</property><!-- 0遇上没有实现的报文(Unknown command:),就会报错、1为忽略该报文,返回ok报文。-->

  5. <property name="defaultSqlParser">druidparser</property>

  6. <property name="serverPort">8066</property>

  7. <property name="managerPort">9066</property>

  8. <property name="idleTimeout">300000</property>

  9. <property name="bindIp">0.0.0.0</property>

  10. </system>

  11. <user name="root" defaultAccount="true">

  12. <property name="password">123456</property>

  13. <property name="schemas">TESTDB</property>

  14. <property name="defaultSchema">TESTDB</property>


  15. <!-- 表级 DML 权限设置 -->

  16. <!--

  17. <privileges check="false">

  18. <schema name="TESTDB" dml="0110" >

  19. <table name="tb01" dml="0000"></table>

  20. <table name="tb02" dml="1111"></table>

  21. </schema>

  22. </privileges>

  23. -->

  24. </user>


  25. <user name="user_r">

  26. <property name="password">123456</property>

  27. <property name="schemas">TESTDB</property>

  28. <property name="readOnly">true</property>

  29. <property name="defaultSchema">TESTDB</property>

  30. </user>

  31. </mycat:server>

说明:

  • 中的TESTDB,不一定是你数据库上的真实库名。只要和schema.xml中可对应用就。

  • 中定义是Mycat账号,并不是MySQL的账号。

  • 注释掉的privileges 表示mycat用户的操作权限。dml 权限顺序为:insert(新增),update(修改),select(查询),delete(删除),0000–> 1111,0 为禁止权限,1 为开启权限。

4.2 schema.xml

Schema.xml 作为 MyCat 中重要的配置文件之一,管理着 MyCat 的逻辑库、表、分片规则、DataNode 以 及 DataSource。

schema.xml:


  • 定义逻辑库,逻辑表


  • 定义数据节点,分片

  • 定义数据节点的物理数据库实例、读写分离配置。

示例:

 
   
   
 
  1. <?xml version="1.0"?>

  2. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">

  3. <mycat:schema xmlns:mycat="http://io.mycat/">


  4. <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" >

  5. <table name="user" dataNode="dn1"/>

  6. </schema>

  7. <dataNode name="dn1" dataHost="userdb-host1" database="test" />

  8. <dataHost name="userdb-host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">

  9. <heartbeat>select user()</heartbeat>

  10. <!-- can have multi write hosts -->

  11. <writeHost host="192.124.64.212" url="192.124.64.212:3307" user="mycat" password="mycat123">

  12. <readHost host="192.124.64.213" url="192.124.64.213:3307" user="mycat" password="mycat123" />

  13. </writeHost>

  14. <writeHost host="192.124.64.213" url="192.124.64.213:3307" user="mycat" password="mycat123"/>

  15. </dataHost>


  16. </mycat:schema>

说明:

  • schema name='xx'中配置的逻辑库名,dataNode中database是实际的后端DB名。

  • writeHost标签上的user,password是实际的MySQL账号密码。

  • 若第一个writeHost不可用,mycat将使用第二个writeHost,即实现高可用。

4.3 rule.xml

rule.xml

  • 定义表使用的分片规则。

  • 定义分片算法

示例:

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>


  2. <!DOCTYPE mycat:rule SYSTEM "rule.dtd">

  3. <mycat:rule xmlns:mycat="http://io.mycat/">

  4. <tableRule name="rule1">

  5. <rule>

  6. <columns>user_id</columns>

  7. <algorithm>func1</algorithm>

  8. </rule>

  9. </tableRule>


  10. <function name="mod-long" class="io.mycat.route.function.PartitionByMod">

  11. <!-- how many data nodes -->

  12. <property name="count">3</property>

  13. </function>


  14. <function name="func1" class="io.mycat.route.function.PartitionByLong">

  15. <property name="partitionCount">8</property>

  16. <property name="partitionLength">128</property>

  17. </function>

  18. </mycat:rule>

4.4 log4j2.xml

日志配置:

  • 使用 Apache log4j管理日志

  • 配置文件为conf/log4j2.xml

  • 定义日志格式。其中 %d{yyyy-MM-dd HH:mm:ss.SSS} 时间信息; %5p 级别; %t 线程信息 ; %m 提示信息 ; %n回车符。

  • 定义日志级别。

配置日志格式:

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <Configuration status="INFO">

  3. <Appenders>

  4. <PatternLayout>

  5. <Pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %5p [%t] (%l) - %m%n</Pattern>

  6. </PatternLayout>

  7. </Appenders>

  8. <Loggers>


  9. <asyncRoot level="debug" includeLocation="true">

  10. <AppenderRef ref="RollingFile"/>

  11. </asyncRoot>

  12. </Loggers>

  13. </Configuration>

  14. 说明:

  15. %d{yyyy-MM-dd HH:mm:ss.SSS} 时间信息; %5p 级别; %t 线程信息 ; %m 提示信息 ; %n回车符

  16. 示例:

  17. 2020-04-05 22:50:53.122 DEBUG [$_NIOREACTOR-7-RW] (io.mycat.backend.mysql.nio.handler.SingleNodeHandler.execute(SingleNodeHandler.java:186)) - rrs.getRunOnSlave() default

4.5 配置动态加载

登录管理端口,可reload @@config;reload @@config_all;来动态加载配置。

 
   
   
 
  1. -- 登录管理端口

  2. mysql -h 192.124.64.214 -P 9066 -uroot -p123456 TESTDB

  3. -- 加载schema.xml配置的调整。

  4. reload @@config;


  5. -- 刷新全部配置

  6. reload @@config_all;

5. MyCat管理

通过MyCat管理端口可以方便地进行MyCat管理。

5.1 查看帮助

 
   
   
 
  1. -- 登录管理端口

  2. mysql -h 192.124.64.214 -P 9066 -uroot -p123456 TESTDB

  3. root@192.124.64.214:9066 : TESTDB > show @@help;

5.2 常用命令

  • show xx;命令可以show datanode, database,version等等。

  • reload @@config;

 
   
   
 
  1. root@192.124.64.214:9066 : TESTDB > show @@version ;

  2. +---------------------------------------------+

  3. | VERSION |

  4. +---------------------------------------------+

  5. | 5.6.29-mycat-1.6.7.4-release-20200105164103 |

  6. +---------------------------------------------+

  7. 1 row in set (0.01 sec)


  8. root@192.124.64.214:9066 : TESTDB > show @@server ;

  9. +--------------+-------------+--------------+------------+---------------+---------------+---------+--------+

  10. | UPTIME | USED_MEMORY | TOTAL_MEMORY | MAX_MEMORY | RELOAD_TIME | ROLLBACK_TIME | CHARSET | STATUS |

  11. +--------------+-------------+--------------+------------+---------------+---------------+---------+--------+

  12. | 40m 8s 911ms | 127388176 | 1029177344 | 3817865216 | 1586100586890 | -1 | utf8 | ON |

  13. +--------------+-------------+--------------+------------+---------------+---------------+---------+--------+

  14. 1 row in set (0.00 sec)


  15. root@192.124.64.214:9066 : TESTDB > show @@datanode;

  16. +------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+

  17. | NAME | DATHOST | INDEX | TYPE | ACTIVE | IDLE | SIZE | EXECUTE | TOTAL_TIME | MAX_TIME | MAX_SQL | RECOVERY_TIME |

  18. +------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+

  19. | dn1 | userdb-host1/test | 0 | mysql | 0 | 8 | 1000 | 269 | 0 | 0 | 0 | -1 |

  20. +------+-------------------+-------+-------+--------+------+------+---------+------------+----------+---------+---------------+

  21. 1 row in set (0.00 sec)


  22. root@192.124.64.214:9066 : TESTDB > show @@database ;

  23. +----------+

  24. | DATABASE |

  25. +----------+

  26. | TESTDB |

  27. +----------+

  28. 1 row in set (0.00 sec)


  29. root@192.124.64.214:9066 : TESTDB > show @@datasource;

  30. +----------+---------------+-------+---------------+------+------+--------+------+------+---------+-----------+------------+

  31. | DATANODE | NAME | TYPE | HOST | PORT | W/R | ACTIVE | IDLE | SIZE | EXECUTE | READ_LOAD | WRITE_LOAD |

  32. +----------+---------------+-------+---------------+------+------+--------+------+------+---------+-----------+------------+

  33. | dn1 | 192.124.64.212 | mysql | 192.124.64.212 | 3307 | W | 0 | 8 | 1000 | 275 | 0 | 4 |

  34. | dn1 | 192.124.64.213 | mysql | 192.124.64.213 | 3307 | W | 0 | 1 | 1000 | 262 | 1 | 0 |

  35. | dn1 | 192.124.64.213 | mysql | 192.124.64.213 | 3307 | R | 0 | 8 | 1000 | 272 | 3 | 0 |

  36. +----------+---------------+-------+---------------+------+------+--------+------+------+---------+-----------+------------+

  37. 3 rows in set (0.01 sec)


  38. root@192.124.64.214:9066 : TESTDB >show @@sql ;

  39. +------+------+---------------+--------------+-------------------------------------+---------------+

  40. | ID | USER | START_TIME | EXECUTE_TIME | SQL | IP |

  41. +------+------+---------------+--------------+-------------------------------------+---------------+

  42. | 1 | root | 1586098782639 | 2 | select * from user where id=1 | 192.110.91.217 |

  43. | 2 | root | 1586098759715 | 3 | select * from user | 192.110.91.217 |

  44. +------+------+---------------+--------------+-------------------------------------+---------------+


  45. root@192.124.64.214:9066 : TESTDB > show @@backend;

  46. +------------+------+---------+---------------+------+--------+--------+---------+------+--------+----------+------------+--------+---------+---------+------------+

  47. | processor | id | mysqlId | host | port | l_port | net_in | net_out | life | closed | borrowed | SEND_QUEUE | schema | charset | txlevel | autocommit |

  48. +------------+------+---------+---------------+------+--------+--------+---------+------+--------+----------+------------+--------+---------+---------+------------+

  49. | Processor0 | 8 | 1193 | 192.124.64.212 | 3307 | 9440 | 2700 | 662 | 2693 | false | false | 0 | test | utf8:33 | 3 | true |

  50. | Processor0 | 15 | 1132 | 192.124.64.213 | 3307 | 34289 | 2779 | 680 | 2393 | false | false | 0 | test | utf8:33 | 3 | true |


  51. +------------+------+---------+---------------+------+--------+--------+---------+------+--------+----------+------------+--------+---------+---------+------------+


  52. root@192.124.64.214:9066 : TESTDB > reload @@config ;

  53. Query OK, 1 row affected (0.05 sec)

6.读写分离测试

6.1 DB环境准备

建好主从库关系,并建测试表user。Master 192.124.64.212:3307,Slave 192.124.64.213:3307。

 
   
   
 
  1. # 在Master 192.124.64.212:3307上建表

  2. mysql -h 192.124.64.212 -P 3307 test

  3. SQL>CREATE TABLE user (

  4. id int(11) NOT NULL AUTO_INCREMENT,

  5. name varchar(32) DEFAULT NULL,

  6. PRIMARY KEY (id)

  7. )

6.2 配置mycat

读写分离需要配置server.xml,schema.xml,不需要配置rule.xml。

6.2.1 server.xml

 
   
   
 
  1. <mycat:server xmlns:mycat="http://io.mycat/">

  2. <system>

  3. <property name="nonePasswordLogin">0</property>

  4. <property name="ignoreUnknownCommand">1</property>

  5. <property name="defaultSqlParser">druidparser</property>

  6. <property name="serverPort">8066</property>

  7. <property name="managerPort">9066</property>

  8. <property name="idleTimeout">300000</property>

  9. <property name="bindIp">0.0.0.0</property>

  10. </system>

  11. <user name="root" defaultAccount="true">

  12. <property name="password">123456</property>

  13. <property name="schemas">TESTDB</property>

  14. <property name="defaultSchema">TESTDB</property>


  15. <user name="user_r">

  16. <property name="password">123456</property>

  17. <property name="schemas">TESTDB</property>

  18. <property name="readOnly">true</property>

  19. <property name="defaultSchema">TESTDB</property>

  20. </user>

  21. </mycat:server>

6.2.2 schema.xml

 
   
   
 
  1. <?xml version="1.0"?>

  2. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">

  3. <mycat:schema xmlns:mycat="http://io.mycat/">

  4. <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" >

  5. <table name="user" dataNode="dn1"/>

  6. </schema>

  7. <dataNode name="dn1" dataHost="userdb-host1" database="test" />

  8. <dataHost name="userdb-host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">

  9. <heartbeat>select user()</heartbeat>

  10. <writeHost host="192.124.64.212" url="192.124.64.212:3307" user="mycat" password="mycat123">

  11. <readHost host="192.124.64.213" url="192.124.64.213:3307" user="mycat" password="mycat123" />

  12. </writeHost>

  13. </dataHost>

  14. </mycat:schema>

6.2.3 log4j2.xml

修改asyncRoot level="debug"。

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <Configuration status="DEBUG">

  3. <Loggers>

  4. <asyncRoot level="debug" includeLocation="true">

  5. <AppenderRef ref="RollingFile"/>

  6. </asyncRoot>

  7. </Loggers>

  8. </Configuration>

6.3 启动MyCat

进入mycat目录,若是单机安装多个mycat可以使用,如下目录。

 
   
   
 
  1. $cd /data1/mycat_server/mycat-user

  2. $./bin/mycat start


  3. #查看启动日志

  4. $tail logs/mycat.log

  5. $tail logs/wrapper.log

  6. INFO | jvm 1 | 2020/04/05 22:50:36 | MyCAT Server startup successfully. see logs in logs/mycat.log

6.4 测试读写

读写数据:

 
   
   
 
  1. #登录mycat

  2. mysql -h 192.124.64.214 -P 8066 -uroot -p123456 TESTDB

  3. #写入数据

  4. (192.124.64.214@8066)[TESTDB]>select * from user;

  5. Empty set (0.08 sec)


  6. (192.124.64.214@8066)[TESTDB]>insert into user values(1,'zhang3');

  7. Query OK, 1 row affected (0.02 sec)


  8. (192.124.64.214@8066)[TESTDB]>insert into user values(2,'li4');

  9. Query OK, 1 row affected (0.01 sec)


  10. (192.124.64.214@8066)[TESTDB]>select * from user;

  11. +----+--------+

  12. | id | name |

  13. +----+--------+

  14. | 1 | zhang3 |

  15. | 2 | li4 |

  16. +----+--------+

  17. 2 rows in set (0.01 sec)

查看日志:

 
   
   
 
  1. $tail -f logs/mycat.log


  2. ## write

  3. 2020-04-05 22:51:08.099 DEBUG [$_NIOREACTOR-7-RW] (io.mycat.server.NonBlockingSession.execute(NonBlockingSession.java:126)) - ServerConnection [id=1, schema=TESTDB, host=192.110.91.217, user=root,txIsolation=3, autocommit=true, schema=TESTDB, executeSql=insert into user values(1,'zhang3')]insert into user values(1,'zhang3'), route={

  4. 1 -> dn1{insert into user values(1,'zhang3')}

  5. } rrs

  6. ...

  7. 2020-04-05 22:51:08.105 DEBUG [$_NIOREACTOR-1-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:386)) - release connection MySQLConnection@720534076 [id=1, lastTime=1586098268090, user=mycat, schema=test, old shema=test, borrowed=true, fromSlaveDB=false, threadId=1194, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{insert into user values(1,'zhang3')}, respHandler=SingleNodeHandler [node=dn1{insert into user values(1,'zhang3')}, packetId=1], host=192.124.64.212, port=3307, statusSync=null, writeQueue=0, modifiedSQLExecuted=true]


  8. ## read


  9. 2020-04-05 22:50:53.124 DEBUG [$_NIOREACTOR-7-RW] (io.mycat.backend.datasource.PhysicalDBNode.getConnection(PhysicalDBNode.java:133)) - rrs.getRunOnSlave() default

  10. 2020-04-05 22:50:53.124 DEBUG [$_NIOREACTOR-7-RW] (io.mycat.backend.datasource.PhysicalDBPool.getRWBanlanceCon(PhysicalDBPool.java:556)) - select read source 192.124.64.213 for dataHost:userdb-host1

  11. 2020-04-05 22:50:53.126 DEBUG [$_NIOREACTOR-5-RW] (io.mycat.server.NonBlockingSession.releaseConnection(NonBlockingSession.java:386)) - release connection MySQLConnection@1477164757 [id=13, lastTime=1586098253110, user=mycat, schema=test, old shema=test, borrowed=true, fromSlaveDB=true, threadId=1130, charset=utf8, txIsolation=3, autocommit=true, attachment=dn1{SELECT *

  12. FROM user

  13. LIMIT 100}, respHandler=SingleNodeHandler [node=dn1{SELECT *

  14. FROM user

  15. LIMIT 100}, packetId=4], host=192.124.64.213, port=3307, statusSync=null, writeQueue=0, modifiedSQLExecuted=false]

说明 :

  • 写时日志:node=dn1{insert into user values(1,'zhang3')}, packetId=1], host=192.124.64.212, port=3307。

  • 读时日志: select read source 192.124.64.213 for dataHost:userdb-host1。

根据日志说明,mycat确实进行了正确的读写分离。

6. 单库分表测试

MyCat较多示例使用的是分库sharding。MyCat1.6版本以后,也可支持单库分表,配置参数为。

6.1 DB环境准备

数据库继续使用上节的192.124.64.212:3307 。分表测试以电商常见的购物车为例,假定购物车分表为shoppingcart0~shoppingcart99。

创建模板表:

 
   
   
 
  1. -- 在主库上创建shoppingcart

  2. mysql -h 192.124.64.212 -P 3307 -u mycat -pmycat123

  3. create database shoppingcart;

  4. -- cart_id 其实常由发号器生成,全局唯一。cart_idshopping_cart_items外键。

  5. create table shopping_cart_0 (

  6. cart_id int(11) NOT NULL AUTO_INCREMENT,

  7. user_id int(10) unsigned not null,

  8. create_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,

  9. PRIMARY KEY (`cart_id`)

  10. )

创建分表:使用shell的for循环来创建分表。

 
   
   
 
  1. for ((i=0;i<=99;i++)) ; do echo "create table shopping_cart_$i like shopping_cart_0"| mysql -h 192.124.64.212 -P 3307 shoppingcart ; done;

6.2 MyCat配置

6.2.1 server.xml

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!DOCTYPE mycat:server SYSTEM "server.dtd">


  3. <mycat:server xmlns:mycat="http://io.mycat/">

  4. <system>

  5. <property name="nonePasswordLogin">0</property>

  6. <property name="ignoreUnknownCommand">1</property>

  7. <property name="defaultSqlParser">druidparser</property>

  8. <property name="serverPort">8066</property>

  9. <property name="managerPort">9066</property>

  10. <property name="idleTimeout">300000</property>

  11. <property name="bindIp">0.0.0.0</property>

  12. <property name="processors">128</property>

  13. <property name="processorExecutor">32</property>

  14. </system>

  15. <user name="root" defaultAccount="true">

  16. <property name="password">123456</property>

  17. <property name="schemas">TESTDB</property>

  18. <property name="defaultSchema">TESTDB</property>

  19. </user>


  20. <user name="user_r">

  21. <property name="password">123456</property>

  22. <property name="schemas">TESTDB</property>

  23. <property name="readOnly">true</property>

  24. <property name="defaultSchema">TESTDB</property>

  25. </user>

  26. </mycat:server>

6.2.2 schema.xml

 
   
   
 
  1. <?xml version="1.0"?>

  2. <!DOCTYPE mycat:schema SYSTEM "schema.dtd">

  3. <mycat:schema xmlns:mycat="http://io.mycat/">


  4. <schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100" >

  5. <table name="shoppingcart" primaryKey="cart_id" dataNode="dn_cart_0" subTables="shopping_cart_$0-99" rule="modByUserId"/>

  6. </schema>

  7. <dataNode name="dn_cart_0" dataHost="cartdb-host1" database="shoppingcart" />

  8. <dataHost name="cartdb-host1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">

  9. <heartbeat>select user()</heartbeat>

  10. <!-- can have multi write hosts -->

  11. <writeHost host="cartM1" url="192.124.64.212:3307" user="mycat" password="mycat123">

  12. <readHost host="cartS1" url="192.124.64.213:3307" user="mycat" password="mycat123" />

  13. </writeHost>

  14. </dataHost>

  15. </mycat:schema>

注意配置中subTables="shoppingcart$0-99" 及rule="modByUserId"。

6.2.3 rule.xml

 
   
   
 
  1. <?xml version="1.0" encoding="UTF-8"?>

  2. <!DOCTYPE mycat:rule SYSTEM "rule.dtd">

  3. <mycat:rule xmlns:mycat="http://io.mycat/">

  4. <tableRule name="modByUserId">

  5. <rule>

  6. <columns>user_id</columns>

  7. <algorithm>mod-long</algorithm>

  8. </rule>

  9. </tableRule>

  10. <function name="mod-long" class="io.mycat.route.function.PartitionByMod">

  11. <!-- how many data nodes ,依子表的数量-->

  12. <property name="count">100</property>

  13. </function>

  14. </mycat:rule>

rule配置分片规则,count中配置为子表的数量,本例中为100。

6.3 启动MyCat

 
   
   
 
  1. $./bin/mycat start

  2. #查看启动日志

  3. $tail logs/mycat.log

6.4 测试分表读写

MyCat写入数据:在mycat中插入几条数据

 
   
   
 
  1. mysql -h 192.124.64.214 -P 8066 -uroot -p123456 TESTDB -A

  2. (192.124.64.214@8066)[TESTDB]>select * from shoppingcart;

  3. Empty set (0.40 sec)


  4. (192.124.64.214@8066)[TESTDB]>show tables;

  5. +------------------+

  6. | Tables in TESTDB |

  7. +------------------+

  8. | shoppingcart |

  9. +------------------+

  10. 1 row in set (0.01 sec)


  11. (192.124.64.214@8066)[TESTDB]>insert into shoppingcart(cart_id,user_id) values(1,101);

  12. Query OK, 1 row affected (0.02 sec)


  13. (192.124.64.214@8066)[TESTDB]>insert into shoppingcart(cart_id,user_id) values(2,102);

  14. Query OK, 1 row affected (0.01 sec)


  15. (192.124.64.214@8066)[TESTDB]>select * from shoppingcart ;

  16. +---------+---------+---------------------+

  17. | cart_id | user_id | create_at |

  18. +---------+---------+---------------------+

  19. | 1 | 101 | 2020-04-06 23:43:50 |

  20. | 2 | 102 | 2020-04-06 23:43:57 |

  21. +---------+---------+---------------------+

  22. 2 rows in set (0.07 sec)

后端MySQL检查:

 
   
   
 
  1. mysql -h 192.124.64.212 -P 3307 shoppingcart -u mycat -pmycat123

  2. mycat@192.124.64.212:3307 : shoppingcart > select * from shopping_cart_1;

  3. +---------+---------+---------------------+

  4. | cart_id | user_id | create_at |

  5. +---------+---------+---------------------+

  6. | 1 | 101 | 2020-04-06 23:43:50 |

  7. +---------+---------+---------------------+

  8. 1 row in set (0.00 sec)


  9. mycat@192.124.64.212:3307 : shoppingcart > select * from shopping_cart_2;

  10. +---------+---------+---------------------+

  11. | cart_id | user_id | create_at |

  12. +---------+---------+---------------------+

  13. | 2 | 102 | 2020-04-06 23:43:57 |

  14. +---------+---------+---------------------+

  15. 1 row in set (0.00 sec)


  16. mycat@192.124.64.212:3307 : shoppingcart > select * from shopping_cart_3;

  17. Empty set (0.00 sec)

参考:

  • 官方 http://www.mycat.org.cn/

  • 指南 http://www.mycat.io/document/mycat-definitive-guide.pdf

  • Mycat水平拆分之十种分片规则

  • http://www.imooc.com/learn/951

  • https://www.jianshu.com/p/fc11d28c67dc