Mycat简介
- 一个数据库中间件产品
- 一个彻底开源的,面向企业应用开发的大数据库集群
- 支持 事务、ACID、可以替代 MySQL的加强版数据库
- 一个可以视为MySQL集群的企业级数据库,用来替代昂贵的Oracle集群
- 一个融合内存缓存技术、NoSQL技术、HDFS大数据的 新型SQL Server结合传统数据库和 新型分布式数据仓库的新一代 企业级数据库产品
参考资料
Mycat 学习文档:http://www.mycat.org.cn/document/mycat-definitive-guide.pdf
mycat 网站:http://www.mycat.org.cn/
java jdk安装博文:https://www.cnblogs.com/wjup/p/11041274.html
mycat github仓库:https://github.com/MyCATApache/Mycat-download
mycat 基本逻辑结构(思维导图):https://kdocs.cn/l/shHheJJd9tG0
Mycat安装
Windows下安装mycat
1、安装 java jdk
安装 java jdk 需要 jdk version > 1.7
2、安装mycat
安装完成后,正常启动bin文件下:
启动startup_nowrap ,直接双击运行 startup_nowrap.bat
或者使用Navicat工具去连接(但是响应时间会很长,不建议使用),推荐使用cmd命令连接mycat
小帖士:本文演示下载的版本地址是:Mycat-server-1.6.7.3
Linux下安装mycat
1、安装 java jdk
1.1、去Oracle官网下载需要安装的jdk版本,我这里用的是 jdk-8u181-linux-x64.tar.gz
1.2、解压安装
# 解压文件
[root@localhost home]# tar -zxvf jdk-8u20-linux-x64.tar.gz
# 移动到 use/local/java 软件安装目录
[root@VM-0-15-centos home]# mv jdk1.8.0_20 /usr/local/java
1.3、接下来就该配置 环境变量
了,输入以下指令进行配置:
[root@localhost home]# vi /etc/profile
# java
set java environment
JAVA_HOME=/usr/local/java
JRE_HOME=/usr/local/java/jre
CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib
PATH=$PATH:$JAVA_HOME/bin:$JRE_HOME/bin
export JAVA_HOME JRE_HOME CLASS_PATH PATH
小帖士:其中 JAVA_HOME, JRE_HOME 请根据自己的实际安装路径及 JDK 版本配置。
1.4、编辑完之后,保存并退出,然后输入以下指令,刷新环境配置使其生效
[root@localhost home]# source /etc/profile
1.5、测试是否安装成功
[root@VM-0-15-centos java]# java -version
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) 64-Bit Server VM (build 25.20-b23, mixed mode)
2、安装mycat
2.1、下载 mycat
后进行解压
[root@VM-0-15-centos home]# tar -zxvf Mycat-server-1.6.7.3-release-20190828135747-linux.tar.gz
2.2、移动到 /usr/local/
目录下
[root@VM-0-15-centos home]# mv mycat /usr/local/mycat
[root@VM-0-15-centos home]# cd /usr/local/mycat/
2.3、启动mycat
# 进入到 bin 目录、启动目录
[root@VM-0-15-centos mycat]# cd bin/
# 查看 mycat 的命令
[root@VM-0-15-centos bin]# ./mycat
Usage: ./mycat { console | start | stop | restart | status | dump }
# 检查mycat是否存在配置错误
[root@VM-0-15-centos bin]# ./mycat console
# 启动mycat
[root@VM-0-15-centos bin]# ./mycat start
2.5、修改 mycat 的 java 服务
# 进入配置文件
vim /usr/local/mycat/conf/wrapper.conf
# 修改 java 的绝对路径的启动服务
wrapper.java.command=/usr/local/java/bin/java
2.4、连接mycat
[root@VM-0-15-centos ~]# mysql -uroot -p123456 -h127.0.0.1 -P8066 --default_auth=mysql_native_password
小帖士:
由于
Mysql8
的缺省加密方式已经改为caching_sha2_password
,而MyCat对此尚不支持。为此,需加
上--default_auth=mysql_native_pasowrd
选项mycat的默认配置密码是
123456
,故这里用123456
登录 mycat
Mycat的使用
配置文件简介
server.xml
该文件几乎保存了所有mycat需要的系统配置信息,包括 mycat 用户管理、DML权限管理等,其在代码内直接的映射类为SystemConfig 类。
Mycat 1.6的用户权限管理是通过server.xml实现的。在server.xml中通过用户标签和防火墙标签进行配置管理的
(1)设置password属性,设置用户的密码
(2)修改 readOnly 为 true 或 false 来限制用户对数据库是否可读写的权限,true为只读,false为读写
(3)修改 schemas 内的文本来控制用户可放问的 schema,多个schema用,号隔开
(4)设置benchmark属性:benchmark 基准, 当前端的整体 connection 数达到基准值是, 对来自该账户的请求开始拒绝连接,0 或不设表示不限制。
(5)设置usingDecrypt属性:是否对密码加密默认 0 否 如需要开启配置 1,同时使用加密程序对密码加密,加密命令方法是执行mycat的jar程序:java -cp Mycat-server-1.6.1-dev.jar org.opencloudb.util.DecryptUtil 0:user:password
vim查看用户配置
(局部配置)信息如下:
<user name="root" defaultAccount="true">
<property name="password">123456</property>
<property name="schemas">TESTDB</property>
<!-- 表级 DML 权限设置 -->
<!--
<privileges check="false">
<schema name="TESTDB" dml="0110" >
<table name="tb01" dml="0000"></table>
<table name="tb02" dml="1111"></table>
</schema>
</privileges>
-->
</user>
schema.xml
用来定义mycat实例中的逻辑库,mycat可以有多个逻辑库,每个逻辑库都有自己的相关配置。可以使用schema标签来划分这些不同的逻辑库。
如果不配置schema标签,所有表的配置会属于同一个默认的逻辑库。
逻辑库的概念和MySql的database的概念一样,我们在查询两个不同逻辑库中的表的时候,需要切换到该逻辑库下进行查询。
(注意:进行查询的时候需要在server.xml配置相关用户权限信息)
vim查看数据源
信息如下
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="0"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<!-- can have multi write hosts -->
<writeHost host="hostM1" url="localhost:3306" user="root"
password="123456">
<!-- can have multi read hosts -->
<readHost host="hostS2" url="192.168.1.200:3306" user="root" password="xxx" />
</writeHost>
<writeHost host="hostS1" url="localhost:3316" user="root"
password="123456" />
<!-- <writeHost host="hostM2" url="localhost:3316" user="root" password="123456"/> -->
</dataHost>
rule.xml
里面就定义了我们对表进行拆分所涉及到的规则定义。我们可以灵活的对表使用不同的分片算法, 或者对表使用相同的算法但具体的参数不同。这个文件里面主要有 tableRule 和 function 这两个标签。在具体使 用过程中可以按照需求添加 tableRule 和 function
Mycat的简单使用
接下来的实现需求如下
- 数据库实现读写分离
- 对于插入的订单数据按照算法,除模取余的方式插入的不同的表中
- 对于查询根据除模取余算法,联查不同的表
- 满足对于那些分库分表后进行查询的业务需求
- 做全局表,实现插入一条数据后,该数据同时插入到对应的n个库中
在schema.xml配置数据源信息
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<!-- 用TESTDB映射对应的数据表 -->
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<!-- 表信息 -->
<!-- subTables 表示0-9十张表 -->
<!-- mod-long 表示对分表进行除模取余实现 -->
<table name="order" primaryKey="id" subTables="order$0-9" dataNode="dn1" rule="mod-long" />
</schema>
<!-- 指定数据源,即数据库 -->
<dataNode name="dn1" dataHost="localhost1" database="my_test_db" />
<!-- 配置数据源连接信息。 balance=3 且实现读写分离 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<!-- 数据节点心跳检测 -->
<heartbeat>select user()</heartbeat>
<!-- write 连接信息 -->
<writeHost host="hostM1" url="127.0.0.1:33061" user="slave"
password="slave">
<!-- read 连接信息 -->
<readHost host="hostS2" url="127.0.0.1:33062" user="slave" password="slave" />
</writeHost>
</dataHost>
</mycat:schema>
映射数据表说明
name=“order” 配置为 order 表
subTables=“order$0-9” 代表创建的10个order表(下文会创建的)
dataNode=“dn1” 表示数据源节点,可用逗号配置多个
rule=“mod-long” 用 除模取余
的方法,插入数据的时候,根据此方法插入到不同的表中。还有其他的方法,可查看 conf/rule.xml
指定数据源说明
name=“dn1” 这里是上文中定义的切片规则时定义的数据节点名称
dataHost=“localhost1” 这里是上文中定义的数据源的 dataHost 的 name
信息
database=“my_test_db” 这里是真实的数据库地址
数据库连接信息说明
balance=“0”, 不开启读写分离机制,所有读操作都发送到当前可用的writeHost上。
balance=“1”,全部的readHost与stand by writeHost参与select语句的负载均衡,简单的说,当双主双从模式(M1->S1,M2->S2,并且M1与 M2互为主备),正常情况下,M2,S1,S2都参与select语句的负载均衡。
balance=“2”,所有读操作都随机的在writeHost、readhost上分发。
balance=“3”,所有读请求随机的分发到wiriterHost对应的readhost执行,writerHost不负担读压力
Tips:请确保连接的账号有足够的权限
mysql> show databases; # 用此检测 slave 能不能查到mycat中配置的 databases
在rule.xml配置分表算法
<function name="mod-long" class="io.mycat.route.function.PartitionByMod">
<!-- how many data nodes -->
<property name="count">10</property>
</function>
因为接下来用 10 张表进行测试,所以我把这里的默认3改成了10
测试配置文件是否有误
# 进入mycat启动目录
[root@VM-0-15-centos home]# cd /usr/local/mycat/bin/
# 进行测试
[root@VM-0-15-centos conf]# ./mycat console
如果输出结果是 successfly 则表示正确,否则请查看日志,分析错误原因
重启mycat服务
[root@VM-0-15-centos bin]# ./mycat stop
Stopping Mycat-server...
Stopped Mycat-server.
[root@VM-0-15-centos bin]# ./mycat start
Starting Mycat-server...
[root@VM-0-15-centos bin]# ./mycat status
Mycat-server is running (19070).
创建测试表进行测试
在端口号为
33061
的数据库服务器创建my_test_db
数据库,然后创建order0~order9
10张表用于测试
CREATE TABLE `order` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`buyer` int(11) DEFAULT NULL,
`name` varchar(20) DEFAULT NULL,
`level` tinyint(4) DEFAULT NULL,
`status` tinyint(4) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
测试mycat
# 连接(-D 指定数据库)
[root@VM-0-15-centos ~]# mysql -uroot -p123456 -h127.0.0.1 -P8066 -DTESTDB --default_auth=mysql_native_password
# 插入一些数据
mysql> INSERT INTO order(id,buyer,name,level,status) VALUE(1,1,1,1,1);
mysql> INSERT INTO order(id,buyer,name,level,status) VALUE(5,9,9,9,9);
mysql> INSERT INTO order(id,buyer,name,level,status) VALUE(8,8,8,8,8);
# 测试查询
mysql> select * from order order by level desc;
+----+-------+------+-------+--------+
| id | buyer | name | level | status |
+----+-------+------+-------+--------+
| 5 | 9 | 9 | 9 | 9 |
| 8 | 8 | 8 | 8 | 8 |
| 1 | 1 | 1 | 1 | 1 |
+----+-------+------+-------+--------+
3 rows in set (0.22 sec)
# 分析被查询的表信息
mysql> explain select * from order order by level desc;
+-----------+----------------------------------------------------+
| DATA_NODE | SQL |
+-----------+----------------------------------------------------+
| dn1 | SELECT * FROM order0 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order1 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order2 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order3 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order4 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order5 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order6 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order7 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order8 ORDER BY level DESC LIMIT 100 |
| dn1 | SELECT * FROM order9 ORDER BY level DESC LIMIT 100 |
+-----------+----------------------------------------------------+
10 rows in set (0.00 sec)
通过可视化工具,看到这些数据已经用 除模取余
的方法,已经插入到不同的表中。
实现全局表
基于上面已经对schema.xml的更改,再做如下更改
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">
<schema name="TESTDB" checkSQLschema="true" sqlMaxLimit="100">
<!--全局表配置-->
<table name="student" primaryKey="id" type="global" dataNode="dn1,dn2,dn3" />
</schema>
<!-- 全局表指定的数据源1 -->
<dataNode name="dn1" dataHost="localhost1" database="my_test_db" />
<!-- 全局表指定的数据源2 -->
<dataNode name="dn2" dataHost="localhost1" database="my_test_db_2" />
<!-- 全局表指定的数据源3 -->
<dataNode name="dn3" dataHost="localhost1" database="my_test_db_3" />
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="3"
writeType="0" dbType="mysql" dbDriver="native" switchType="1" slaveThreshold="100">
<heartbeat>select user()</heartbeat>
<writeHost host="hostM1" url="127.0.0.1:33061" user="root"
password="root">
<readHost host="hostS2" url="127.0.0.1:33062" user="root" password="root" />
</writeHost>
</dataHost>
</mycat:schema>
进行测试
需要现在三个数据库(my_test_db、my_test_db_2、my_test_db_3)创建同样结构的表
然后连接 mycat 服务
开始插入数据
mysql> INSERT INTO student(id,name) VALUE(1,1);
Query OK, 1 row affected (0.30 sec)
然后,通过数据库管理工具,可以看到三个数据库都已经新增了这条数据
但是通过mycat却只能查到一个,这就是用mycat做数据库中间件的好处
mysql> select * from student;
+----+------+
| id | name |
+----+------+
| 1 | 1 |
+----+------+
1 row in set (0.06 sec)
问题
1、命令窗使用mycat第一次查询或者插入出现如下错误,然后紧接着第二次操作错误消失
错误描述: ERROR 2006 (HY000): MySQL server has gone away
解决方案: 出现此错误的原因是,mycat和mysql建立了一个连接后,长时间没有操作mysql,mysql会自动把这个连接 kill 掉。你可以通过配置mysql的 max_allowed_packed
进行解决