Window平台MYCAT实现读写分离
一.安装
Mycat官网:http://www.mycat.io/

Mycat下载地址:http://dl.mycat.io/

下载:建议大家选择 1.6-RELEASE 版本,毕竟是比较稳定的版本。
安装:根据不同的系统选择不同的版本。包括linux、windows、mac,作者考虑还是非常周全的,当然,也有源码版的。(源码版的下载后,只要配置正确,就可以正常运行调试)
Mycat的安装其实只要解压下载的目录就可以了,非常简单。
安装完成后,目录如下:

目录 | 说明 |
bin | mycat命令,启动、重启、停止等 |
catlet | catlet为Mycat的一个扩展功能 |
conf | Mycat 配置信息,重点关注 |
lib | Mycat引用的jar包,Mycat是java开发的 |
logs | 日志文件,包括Mycat启动的日志和运行的日志。 |
配置
Mycat的配置文件都在conf目录里面,这里介绍几个常用的文件:
文件 | 说明 |
server.xml | Mycat的配置文件,设置账号、参数等 |
schema.xml | Mycat对应的物理数据库和数据库表的配置 |
rule.xml | Mycat分片(分库分表)规则 |
Mycat的架构其实很好理解,Mycat是代理,Mycat后面就是物理数据库。和Web服务器的Nginx类似。对于使用者来说,访问的都是Mycat,不会接触到后端的数据库。
我们现在做一个主从、读写分离,简单分表的示例。结构如下图:

服务器 | IP | 说明 |
Mycat | 127.0.0.1:8066 | mycat服务器,连接数据库时,连接此服务器 |
Database1 | 127.0.0.1:3306 | 物理数据库1,真正存储数据的数据库 |
Database2 | 127.0.0.1:3307 | 物理数据库1,真正存储数据的数据库 |
Database3 | 127.0.0.1:3308 | 物理数据库2,真正存储数据的数据库 |
Mycat作为主数据库中间件,肯定是与代码弱关联的,所以代码是不用修改的,使用Mycat后,连接数据库是不变的,默认端口是8066。连接方式和普通数据库一样,如:jdbc:mysql://127.0.0.1:8066/
1.1 修改配置文件
1.1.1 修改wrapper.conf
路径:D:\mycat\conf\wrapper.conf
修改第5行wrapper.java.command为当前JDK路径

1.1.2 修改Server.xml
路径:D:\mycat\conf\Server.xml

重点关注下面这段,其他默认即可。
参数 | 说明 |
user | 用户配置节点 |
--name | 登录的用户名,也就是连接Mycat的用户名 |
--password | 登录的密码,也就是连接Mycat的密码 |
--schemas | 数据库名,这里会和schema.xml中的配置关联,多个用逗号分开,例如需要这个用户需要管理两个数据库db1,db2,则配置db1,dbs |
--privileges | 配置用户针对表的增删改查的权限,具体见文档吧 |
我这里配置了一个账号root密码也是root,针对数据库TESTDB,读写权限都有,没有针对表做任何特殊的权限。
1.1.3 修改Schema.xml
路径:D:\mycat\conf\Schema.xml
重点说明:在配置的过程中需要把连接MySQL的驱动包放到mycat的lib下面

schema.xml是最主要的配置项。
参数 | 说明 |
schema | 数据库设置,此数据库为逻辑数据库,name与server.xml中schema对应 |
dataNode | 分片信息,也就是分库相关配置 |
dataHost | 物理数据库,真正存储数据的数据库 |
每个节点的属性逐一说明:
schema节点:
属性 | 说明 |
name | 逻辑数据库名,与server.xml中的schema对应 |
checkSQLschema | 数据库前缀相关设置,建议看文档,这里暂时设为folse |
sqlMaxLimit | select 时默认的limit,避免查询全表 |
table节点:
属性 | 说明 |
name | 表名,物理数据库中表名 |
dataNode | 表存储到哪些节点,多个节点用逗号分隔。节点为下文dataNode设置的name |
primaryKey | 主键字段名,自动生成主键时需要设置 |
autoIncrement | 是否自增 |
rule | 分片规则名,具体规则下文rule详细介绍 |
dataNode节点:
属性 | 说明 |
name | 节点名,与table中dataNode对应 |
datahost | 物理数据库名,与datahost中name对应 |
database | 物理数据库中数据库名 |
dataHost节点:
属性 | 说明 |
name | 物理数据库名,与dataNode中dataHost对应 |
balance | 均衡负载的方式 |
writeType | 写入方式 |
dbType | 数据库类型 |
heartbeat | 心跳检测语句,注意语句结尾的分号要加。 |
1.2 配置环境变量


二.应用场景
2.1 数据库分表分库
配置如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM"schema.dtd">
<mycat:schemaxmlns:mycat="http://io.mycat/">
<!-- 数据库配置,与server.xml中的数据库对应-->
<schema name="lunch" checkSQLschema="false"sqlMaxLimit="100">
<table name="lunchmenu" dataNode="dn1" />
<table name="restaurant" dataNode="dn1" />
<table name="userlunch" dataNode="dn1" />
<table name="users" dataNode="dn1" />
<table name="dictionary" primaryKey="id" autoIncrement="true"dataNode="dn1,dn2" rule="mod-long" />
</schema>
<!-- 分片配置 -->
<dataNode name="dn1" dataHost="test1"database="lunch" />
<dataNode name="dn2" dataHost="test2"database="lunch" />
<!-- 物理数据库配置 -->
<dataHost name="test1" maxCon="1000"minCon="10" balance="0" writeType="0" dbType="mysql"dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="hostM1" url="192.168.0.2:3306"user="root" password="123456">
</writeHost>
</dataHost>
<dataHost name="test2" maxCon="1000"minCon="10" balance="0" writeType="0"dbType="mysql" dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="hostS1" url="192.168.0.3:3306"user="root" password="123456">
</writeHost>
</dataHost>
</mycat:schema>
我在192.168.0.2、192.168.0.3均有数据库lunch。
lunchmenu、restaurant、userlunch、users这些表都只写入节点dn1,也就是192.168.0.2这个服务,而dictionary写入了dn1、dn2两个节点,也就是192.168.0.2、192.168.0.3这两台服务器。分片的规则为:mod-long。
主要关注rule属性,rule属性的内容来源于rule.xml这个文件,Mycat支持10种分表分库的规则,基本能满足你所需要的要求,这个必须赞一个,其他数据库中间件好像都没有这么多。
table中的rule属性对应的就是rule.xml文件中tableRule的name,具体有哪些分表和分库的实现,建议还是看下文档。我这里选择的mod-long就是将数据平均拆分。因为我后端是两台物理库,所以rule.xml中mod-long对应的function count为2,见下面部分代码:
<tableRule name="mod-long">
<rule>
<columns>id</columns>
<algorithm>mod-long</algorithm>
</rule>
</tableRule>
<function name="mod-long"class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">2</property>
</function>
2.2 数据库读写分离
配置如下:
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM"schema.dtd">
<mycat:schemaxmlns:mycat="http://io.mycat/">
<!-- 数据库配置,与server.xml中的数据库对应-->
<schema name="lunch" checkSQLschema="false"sqlMaxLimit="100">
<table name="lunchmenu" dataNode="dn1" />
<table name="restaurant" dataNode="dn1" />
<table name="userlunch" dataNode="dn1" />
<table name="users" dataNode="dn1" />
<table name="dictionary" primaryKey="id"autoIncrement="true" dataNode="dn1" />
</schema>
<!-- 分片配置 -->
<dataNode name="dn1" dataHost="test1"database="lunch" />
<!-- 物理数据库配置 -->
<dataHost name="test1" maxCon="1000"minCon="10" balance="1" writeType="0" dbType="mysql"dbDriver="native">
<heartbeat>select user();</heartbeat>
<writeHost host="hostM1" url="192.168.0.2:3306"user="root" password="root">
<readHost host="hostM1" url="192.168.0.3:3306"user="root" password=" root ">
</readHost>
</writeHost>
</dataHost>
</mycat:schema>
这样的配置与前一个示例配置改动如下:
删除了table分配的规则,以及datanode只有一个
datahost也只有一台,但是writehost总添加了readhost,balance改为1,表示读写分离。
以上配置达到的效果就是102.168.0.2为主库,192.168.0.3为从库。
注意:Mycat主从分离只是在读的时候做了处理,写入数据的时候,只会写入到writehost,需要通过mycat的主从复制将数据复制到readhost,这个问题当时候我纠结了好久,数据写入writehost后,readhost一直没有数据,以为是自己配置的问题,后面才发现Mycat就没有实现主从复制的功能,毕竟数据库本身自带的这个功能才是最高效稳定的。
至于其他的场景,如同时主从和分表分库也是支持的了,只要了解这个实现以后再去修改配置,都是可以实现的。而热备及故障专业官方推荐使用haproxy配合一起使用,大家可以试试。
三.使用
3.1 常用命令
Mycat的启动也很简单,启动命令在Bin目录:
##启动mycat start
##停止mycat stop
##重启mycat restart
如果在启动时发现异常,在logs目录中查看日志。
wrapper.log 为程序启动的日志,启动时的问题看这个
mycat.log 为脚本执行时的日志,SQL脚本执行报错后的具体错误内容,查看这个文件。mycat.log是最新的错误日志,历史日志会根据时间生成目录保存。
mycat启动后,执行命令不成功,可能实际上配置有错误,导致后面的命令没有很好的执行。
3.2 连接Mycat
Mycat带来的最大好处就是使用是完全不用修改原有代码的,在mycat通过命令启动后,你只需要将数据库连接切换到Mycat的地址就可以了。如下面就可以进行连接了:
mysql -h127.0.0.1 -P8066-uroot –proot
连接成功后可以执行sql脚本了。
所以,可以直接通过sql管理工具(如:navicat、datagrip)连接,执行脚本。
四.常见问题
使用Mycat后总会遇到一些坑,我将自己遇到的一些问题在这里列一下
4.1 Mycat是不是配置以后,就能完全解决分表分库和读写分离问题?
Mycat配合数据库本身的复制功能,可以解决读写分离的问题,但是针对分表分库的问题,不是完美的解决。或者说,至今为止,业界没有完美的解决方案。
分表分库写入能完美解决,但是,不能完美解决主要是联表查询的问题,Mycat支持两个表联表的查询,多余两个表的查询不支持。其实,很多数据库中间件关于分表分库后查询的问题,都是需要自己实现的,而且节本都不支持联表查询,Mycat已经算做地非常先进了。
分表分库的后联表查询问题,大家通过合理数据库设计来避免。
4.2 Mycat支持哪些数据库,其他平台如 .net、PHP能用吗?
官方说了,支持的数据库包括MySQL、SQL Server、Oracle、DB2、PostgreSQL 等主流数据库,很赞。尽量用Mysql,我试过SQL Server,会有些小问题,因为部分语法有点差异。
五.MyCAT监控命令
MyCAT自身有类似其他数据库的管理监控方式,通过Mysql命令行,登录管理端口(9066)执行相应的SQL,进行管理
使用mysql-uroot -proot -P9066 -h127.0.0.1命令进行登录
连接后可以根据管理命令查看Mycat的运行情况,当然,喜欢UI管理方式的人,可以安装一个Mycat-Web来进行管理,有兴趣自行搜索。
show @@help
此命令会显示所有的管理监控命令,另外请参照《Mycat命令行监控指南.docx》这个文档来深入了解。
监控命令汇总show@@help;命令的运行结果如下所示:
常用监控命令介绍
reload @@config;
该命令用于更新配置文件,例如更新schema.xml文件后在命令行窗口输入该命令,可不用重启即进行配置文件更新。
show @@database;
该命令用于显示MyCAT的数据库的列表,对应schema.xml配置文件的schema子节点
show @@datanode;
该命令用于显示MyCAT的数据节点的列表,对应schema.xml配置文件的dataNode节点
其中,“NAME”表示dataNode的名称;“dataHost”表示对应dataHost属性的值,即数据主机;“ACTIVE”表示活跃连接数;“IDLE”表示闲置连接数;“SIZE”对应总连接数量。运行如下命令,可查找对应的schema下面的dataNode列表:show @@datanode where schema = ?
show @@heartbeat;
该命令用于报告心跳状态
show @@version;
该命令用于获取MyCAT的版本
show @@sql.slow;
该命令用于查询运行缓慢的SQL语句
Show @@backend
显示后端物理库连接信息,包括当前连接数,端口
Show @@connection
显示当前前端客户端连接情况,已经网络流量信息。如 KILL @@CONNECTION 26907; 杀掉客户端的连接,参数为连接的ID值,通过show @@connection,可以展示当前连接到MyCAT的所有客户端进程,若某个进程异常,则可以通过该命令杀掉连接
Show @@threadpool
当前线程池的执行情况,是否有积压(active_count)以及task_queue_size,后者为积压的待处理的SQL,若积压数目一直保值,则说明后端物理连接可能不够或者SQL执行比较缓慢。
Show @@heartbeat
当前后端物理库的心跳检测情况,RS_CODE为1表示心跳正常
Show @@datanode
显示数据节点的访问情况,包括每个数据节点当前活动连接数(active),空闲连接数(idle)以及最大连接数(maxCon) size,EXECUTE参数表示从该节点获取连接的次数,次数越多,说明访问该节点越多。
Show @@processor
显示当前processors的处理情况,包括每个processor的IO吞吐量(NET_IN/NET_OUT)、IO队列的积压情况(R_QUEY/W_QUEUE),Socket Buffer Pool的使用情况BU_PERCENT为已使用的百分比、BU_WARNS为Socket Buffer Pool不够时,临时创新的新的BUFFER的次数,若百分比经常超过90%并且BU_WARNS>0,则表明BUFFER不够,需要增大,参见性能调优手册。
Show @@datasource
显示数据源的信息,是否是读写节点等。
show @@cache
显示缓存的使用情况,对于性能监控和调优很有价值
MAX为缓存的最大值(记录个数),CUR为当前已经在缓存中的数量,ACESS为缓存读次数,HIT为缓存命中次数,PUT 为写缓存次数,LAST_XX为最后操作时间戳,比较重要的几个参数:CUR:若CUR接近MAX,而PUT大于MAX很多,则表明MAX需要增大,HIT/ACCESS为缓存命中率,这个值越高越好。
Kill @@connection
杀掉客户端的连接,参数为连接的ID值,通过show @@connection,可以展示当前连接到MyCAT所有客户端进程,若某进程异常,则可通过该命令杀掉连接,如Kill @@connection 1;
reload @@config;
重新加载配置文件schema.xml,如果我们在原有的schema.xml中进行了修改,需要重新加载该文件使其生效。最后只需要重启mycat即可。
六.参考
《Mycat权威指南》: http://www.mycat.io/document/Mycat_V1.6.0.pdf




