参考文档
Mycat2官方语雀文档:Mycat2权威指南 (yuque.com)
Mycat2注释配置:通过注释配置 (yuque.com)
Mycat2映射关系:mycat2映射关系.pdf
创建镜像
1.创建文件夹用于挂载Mycat相关数据卷
mkdir /home/docker/mycat2
cd /home/docker/mycat2
2.创建镜像文件
在/home/docker/mycat2下创建Dockerfile,内容如下:
FROM openjdk:8-jre
ENV AUTO_RUN_DIR ./mycat2
ENV DEPENDENCE_FILE mycat2-1.22-release-jar-with-dependencies.jar
ENV TEMPLATE_FILE mycat2-install-template-1.21.zip
RUN sed -i "s@http://.*archive.ubuntu.com@http://mirrors.aliyun.com@g" /etc/apt/sources.list
RUN sed -i "s@http://.*security.ubuntu.com@http://mirrors.aliyun.com@g" /etc/apt/sources.list
RUN buildDeps='procps wget unzip' \
&& apt-get update \
&& apt-get install -y $buildDeps
# 安装地址 http://dl.mycat.org.cn/2.0/
# http://dl.mycat.org.cn/2.0/1.22-release/
# http://dl.mycat.org.cn/2.0/install-template/
RUN wget -P $AUTO_RUN_DIR/ http://dl.mycat.org.cn/2.0/1.22-release/$DEPENDENCE_FILE \
&& wget -P $AUTO_RUN_DIR/ http://dl.mycat.org.cn/2.0/install-template/$TEMPLATE_FILE
RUN cd $AUTO_RUN_DIR/ \
&& unzip $TEMPLATE_FILE \
&& ls -al . \
&& mv $DEPENDENCE_FILE mycat/lib/ \
&& chmod +x mycat/bin/* \
&& chmod 755 mycat/lib/* \
&& mv mycat /usr/local
#copy mycat /usr/local/mycat/
VOLUME /usr/local/mycat/conf
VOLUME /usr/local/mycat/logs
EXPOSE 8066 1984
CMD ["/usr/local/mycat/bin/mycat", "console"]
3..编译镜像
docker build -t mycat/mycat2:20230801 .
4.mysql用户创建
为mycat用户单独在mysql中创建一个用户,并赋予权限
CREATE USER 'mycat'@'%' IDENTIFIED BY '123456';
-- MySQL8.0版本必须要赋的权限
GRANT XA_RECOVER_ADMIN ON *.* TO 'root'@'%';
--- 视情况赋的权限
GRANT ALL PRIVILEGES ON *.* TO 'mycat'@'%' ;
flush privileges;
构建镜像
启动容器并复制配置
docker run -d --name=mycat2 -p 8066:8066 -p 1984:1984 mycat/mycat2:20230801
# 复制容器内配置
cd /home/docker/mycat2/
docker cp mycat2:/usr/local/mycat/conf .
docker cp mycat2:/usr/local/mycat/logs .
config目录如下:
启动Mycat2
关闭并删除之前运行的容器,重新运行一个mycat2,记得开放端口!
docker run -d
--name=mycat2
-p 8066:8066 -p 1984:1984
-v $PWD/conf:/usr/local/mycat/conf
-v $PWD/logs:/usr/local/mycat/logs
4baac999529e(mycat2镜像ID)
Mycat2配置
运行后肯定会报错,因为我们还没有对Mycat2做任何配置,日志可在 /home/docker/mycat2/logs/wrapper.log 中查看。
Mycat2的配置结构如下:
mycat配置文件夹
+ clusters
- prototype.cluster.json //无集群的时候自动创建
- c0.cluster.json
- c1.cluster.json
+ datasources
- prototypeDs.datasource.json //无数据源的时候自动创建
- dr0.datasource.json
- dw0.datasource.json
+ schemas
- db1.schema.json
- mysql.schema.json
+ sequences
- db1_schema.sequence.json
-server.json //服务器配置
-state.json //mycat运行状态,包含集群选举的主节点信息,配置时间戳
其中:
- datasources/prototypeDs.datasource.json为真实物理数据库的连接配置信息
- schemas/databaseName.schema.json主要配置逻辑表与物理表的关系及分库分表规则
我们需要经常修改的也就是上面两个文件
1.配置真实数据源
vi conf/datasourcesprototypeDs.datasource.json
改为自己物理数据库的连接信息,也可以配置成刚刚创建的用户
{
"dbType":"mysql",
"idleTimeout":60000,
"initSqls":[],
"initSqlsGetConnection":true,
"instanceType":"READ_WRITE", // 当前库既是写库也是读库
"maxCon":1000,
"maxConnectTimeout":3000,
"maxRetryCount":5,
"minCon":1,
"name":"prototypeDs", // 逻辑库名称,不需要修改
"password":"123456", // 数据库密码
"type":"JDBC",
"url":"jdbc:mysql://IP地址:3306/testdb?useUnicode=true&serverTimezone=Asia/Shanghai&characterEncoding=UTF-8",
"user":"mycat", // 数据库用户名
"weight":0
}
2.查看或修改Mycat登录用户信息
vi /home/docker/mycat2/conf/users/root.user.json
{
"dialect":"mysql",
"ip":null, # 如果设置IP,则只能允许该IP使用该用户登录mycat
"password":"123456", // 密码
"transactionType":"proxy", //事务类型
"username":"root" // 用户名
}
可以直接用此账号登录Mycat。
不涉及跨库事务请把事务类型(transactionType)改成proxy,不要使用XA
3.登录Mycat,并创建数据库
使用root.user.json中的账号密码登录Mycat,端口8066,并创建一个数据库,我这里与物理库名一致。
CREATE DATABASE testdb;
此时 /conf/schemas文件夹下会多出一个 testdb.schema.json 的文件。内容如下:
{
"customTables":{},
"globalTables":{},
"normalProcedures":{},
"normalTables":{},
"schemaName":"note",
"shardingTables":{},
"views":{}
}
4.配置表分片规则
后面所有对 testdb 库中的表进行分片规则都可以直接在 /conf/schemas/testdb.schema.json 中来进行配置,也可以使用带有 mycat2 语法的SQL建表语句来指定分片键和分片规则。相比于Mycat1.6来说方便了太多。
分库分表语法文档:DDL语句 (yuque.com)
在Mycat客户端的testdb库创建要进行分片的表(虚拟表),并指定分片规则:
CREATE TABLE `test_sharding` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`add_time` bigint(20) NOT NULL COMMENT '创建时间',
`text` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '测试文本',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 tbpartition by MOD_HASH(id) tbpartitions 3;
其中:tbpartition by MOD_HASH(id) tbpartitions 3; 的含义为 test_sharding 该表需要按照 id 字段哈希取模(即分区值 % 总分区点)来分区,且分区点有三个,分别对应 test_sharding_0、test_sharding_1、test_sharding_2,所以需要先要在物理库中保证这三张表存在。
同样的,如果要进行分库,可以加上 dbpartition by MOD_HASH(id) dbpartitions 数据库数量;
创建完虚拟表后,查看 /conf/schemas/testdb.schema.json 会看到多出来了些配置信息。还需要添加些配置,内容如下:
{
"customTables": { },
"globalTables": { },
"normalProcedures": { },
"normalTables": { },
"schemaName": "testdb", // 逻辑库名
"shardingTables": {
"test_sharding": {
<!-- 建表SQL -->
"createTableSQL": "CREATE TABLE `test_sharding` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`add_time` bigint(20) NOT NULL COMMENT '创建时间',
`text` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '测试文本',
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARSET = utf8mb4
TBPARTITION BY MOD_HASH(id) TBPARTITIONS 3",
"autoIncrement": false,
"function": {
"properties": {
"mappingFormat": "prototype/testdb/test_sharding_${tableIndex}",
"tableNum": "3", # 分区表的数量
"tableMethod": "MOD_HASH(id)", #使用哈希取模算法分区
"storeNum": 0,
"defaultNode": "0",
"type": "Integer"
},
"partition": {
"schemaNames": "testdb", #物理库
"tableNames": "test_sharding_$0-2", #物理表
"targetNames": "prototype" #数据源
}
},
"shardingIndexTables": { }
}
},
"targetName":"prototypeDs",
"views": { }
}
或
{
"customTables": { },
"globalTables": { },
"normalProcedures": { },
"normalTables": { },
"schemaName": "testdb", // 逻辑库名
"shardingTables": {
"test_sharding": {
<!-- 建表SQL -->
"createTableSQL": "CREATE TABLE `test_sharding` (
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
`add_time` bigint(20) NOT NULL COMMENT '创建时间',
`text` varchar(255) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '测试文本',
PRIMARY KEY (`id`)
) ENGINE = InnoDB CHARSET = utf8mb4
TBPARTITION BY MOD_HASH(id) TBPARTITIONS 3",
"function": {
"properties": {
"mappingFormat": "prototype/testdb/test_sharding_${tableIndex}",
"tableNum": "3", # 分区表的数量
"tableMethod": "MOD_HASH(id)", #使用哈希取模算法分区
"storeNum": 0,
}
},
"shardingIndexTables": { }
}
},
"targetName":"prototypeDs",
"views": { }
}
其中,分区算法及配置样例可参考:Mycat 2 规则范围分片算法(对应1.6) (yuque.com)
注意:
如果逻辑库与物理库混淆的话,会导致数据插入错数据库的错误。
需要创建不需要被分库分表的表,直接在Mycat客户端执行建表语句即可,对应配置会同步到normalTables中。
测试
在应用层连接MySql的地址直接改为连接Mycat,端口8066,连接信息在conf/users/root.user.json中。
往 test_sharding 表中连续插入数据可以看到数据被分配到了不同的表中:
其中 id 是Mycat生成的全局唯一ID。
并且在Mycat中进行 select * 查询也能将物理库中三张表的数据一起查询出来。
注意
Mycat的原理中最重要的一个动词是“拦截”,它拦截用户发送的 SQL 语句,首先对 SQL语句做一些特定的分析:如分片分析、路由分析、读写分离分析、缓存分析等,然后将此 SQL 发往真实数据库,并将返回的结果做适当的处理,最终再返回给用户。
所以Mycat中的库与表也被称为“虚拟库”与“虚拟表”,并且“虚拟表”不允许在可视化客户端修改其表结构,只能手动通过DDL语句进行修改。
补充
Q:如何怎么把已经存在的物理表加载到mycat中?
A:使用schema配置中的targetName,指向目标数据源或者集群,同时保证schema的名字与目标的库相同,即可自动加载该库已经存在的物理表
重启mycat或者用注释重新读取Mycat配置文件./*+mycat:loadConfigFromFile{} */把本地配置加载到运行时
在使用Group By时,查询不在Group By中的字段且无函数,则需要使用any_value。
order by必须引用select item中存在的字段