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

image-20210220163548341

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的简单使用

接下来的实现需求如下

  1. 数据库实现读写分离
  2. 对于插入的订单数据按照算法,除模取余的方式插入的不同的表中
  3. 对于查询根据除模取余算法,联查不同的表
  4. 满足对于那些分库分表后进行查询的业务需求
  5. 做全局表,实现插入一条数据后,该数据同时插入到对应的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 进行解决