简介:MyCat 2 的 1.21 版本安装模板压缩包,面向需要快速搭建分布式数据库中间件的开发与运维人员。MyCat 2 是 Java 编写的开源分库分表中间件,支持读写分离、SQL 路由与分布式事务;该模板将启动脚本、核心配置和环境依赖整合在一起,省去手工部署时的多处调整。压缩包共 52 个文件,大小约 1.19MB,以 sql、json、xml、properties 等配置与脚本为主,同时附带面向 Linux/Windows/macOS 等系统的 wrapper 可执行文件及动态库,便于在不同平台直接启动服务。截至目前已有 640 人学习下载。解压后可看到完整目录结构:conf 集中日志、数据源、用户、集群等配置,sql 目录提供初始化表结构与序列脚本,bin 内置 mycat/mycat.bat 启停命令。对初学者,这是一份可运行的部署样例,能对照理解各配置项的作用;对生产团队,也可作为规范化安装和快速排错的基础。
1. 为什么还需要一份 MyCat2 安装模板:从 1.x 迁移到 2.x 的第一个坑
拿到mycat2-install-template-1.21.zip的第一反应,很多人会以为里面躺着熟悉的schema.xml、rule.xml,结果一解压发现全是.json和一堆wrapper-*可执行文件,当场翻车。我当初从 MyCat 1.x 迁到 MyCat 2.x 时就是这样:照着老博客改配置,启动脚本一跑直接报Unable to start JVM,后来才发现模板里的wrapper.conf、conf/datasources、conf/schemas才是 2.x 的核心。这份模板的价值在于,它把 MyCat2 部署所需的最小文件集和跨平台启动器打包好了,你不需要去源码仓库里一个个找依赖,解压、调 JDK、改数据源、起服务,就能得到一个可用的分布式数据库中间件。适合第一次接触 MyCat2 的 DBA、需要快速搭测试环境的 Java 后端,以及正在维护 1.x 想评估升级成本的运维。
2. 拆开 mycat2-install-template-1.21.zip:目录结构与每个文件的作用
2.1 bin 目录:wrapper 脚本和跨平台启动器
bin目录是模板里最容易被忽略却又最关键的部分。mycat和mycat.bat是启动/停止/重启的统一入口,其他以wrapper-开头的文件则是 Tanuki Java Service Wrapper 的本地守护程序。MyCat2 本身是 Java 应用,但直接java -jar启动不利于守护和崩溃自拉起,所以官方模板用 Wrapper 把进程包了一层:bin/mycat start最终会调用对应平台的wrapper-*可执行文件,由它拉起 JVM 并监听退出状态。
模板里带了一堆不同 CPU/OS 的 wrapper 可执行文件,包括wrapper-aix-ppc-32、wrapper-solaris-sparc-32、wrapper-linux-ppc-64、wrapper-windows-x86-32.exe等。实际部署时你几乎只用得上wrapper-linux-x86-64或wrapper-windows-x86-64.exe,其余纯属打包时为跨平台兜底。我一般会把无关平台文件直接删掉,只留本机对应的那个,这样既节省空间,也避免误用导致启动失败。
bin/mycat脚本本身是一个标准的 init 风格包装器,支持start、stop、restart、status。它做的事很简单:检查wrapper.conf是否存在,找到 Java 命令,然后调用 wrapper 可执行文件。所以如果你换过 JDK 路径,优先去wrapper.conf里改,而不是改bin/mycat里的逻辑。
2.2 conf 目录:MyCat2 的 JSON 配置体系
MyCat2 最大的变化之一,就是放弃了 1.x 的 XML 配置家族,全面转向 JSON。conf目录下除了server.json、wrapper.conf、logback.xml这些单文件,还出现了schemas、datasources、clusters、users四个子目录。这四个目录分别对应 MyCat2 的逻辑库、物理数据源、集群分组和用户权限,职责与 1.x 的schema.xml中的<schema>、<dataHost>、<dataNode>、<user>一一对应,但拆分成了按目录管理的 JSON 文件。
server.json是 MyCat 服务本身的配置,比如监听 IP、端口、序列生成策略。模板里的server.json默认端口是 8066,注意别把它当成 MySQL 的 3306。wrapper.conf是 JVM 参数的大本营,wrapper.java.initmemory控制初始堆,wrapper.java.maxmemory控制最大堆,改错这里启动必挂。logback.xml是日志框架配置,MyCat2 用 logback 而不是 log4j,所以日志输出格式和滚动策略都在这里调。
sequences和dbseq.sql是用来做全局序列的。dbseq.sql是一个建表脚本,如果你要使用数据库方式生成分布式 ID,就需要先在后端 MySQL 里执行它。sql目录里放着模板自带的初始化 SQL,具体内容要看版本,但通常包含mycat内部表的建表语句,别小看它。
2.3 lib 目录与 logs:wrapper 的本地库到底在干嘛
lib目录下是一堆libwrapper-*.so、libwrapper-*.a、libwrapper-*.jnilib、libwrapper-*.dll和一个wrapper.jar。这些是 Wrapper 的本地库,作用是在操作系统层做进程控制、信号捕获和输出重定向。简单说,bin目录下的 wrapper 可执行文件负责“启动外部进程”,libwrapper-*.so负责“和 Java 层对话”,wrapper.jar则提供 Java 侧的 Wrapper 接口。版本必须匹配:Linux x86_64 平台要同时有wrapper-linux-x86-64和libwrapper-linux-x86-64.so,缺失或者混搭会直接导致UnsatisfiedLinkError或者启动后无日志。
logs目录默认是空的,但第一次启动后会产生wrapper.log和mycat.log。wrapper.log记录 JVM 启动、崩溃、重启这种底层事件;mycat.log才是 MyCat 本身的业务日志。排查问题第一步永远是看这两个文件,而不是看终端输出。我见过不少同事在bin/mycat start后终端没有任何报错就觉得万事大吉,实际上 JVM 根本没起来,全在wrapper.log里躺着。
# 把模板解压到 /opt/mycat2 unzip mycat2-install-template-1.21.zip -d /opt/mycat2 cd /opt/mycat2 # 查看启动脚本支持的子命令 bin/mycat status上面的命令只是验证脚本能不能跑。注意bin/mycat status输出中如果提示not running,说明 Wrapper 框架启动正常但你还没启动服务。如果提示一些can't load wrapper之类的错误,就是bin与lib下的 wrapper 版本或平台不匹配,优先检查这两个目录里的文件是否来自同一个平台。
3. 把模板变成可用实例:从解压到启动的完整配置路径
3.1 环境准备:JDK 版本选择和 wrapper.conf 调整
MyCat2 基于 Java 8 开发,实测在 JDK 8 和 JDK 11 上都能跑,但我一般固定在 JDK 8。原因不是 JDK 11 不行,而是很多公司内部运维脚本、监控 agent 都按 JDK 8 路径写死,换版本容易触发其他问题。安装模板不会帮你装 JDK,它只负责启动已经存在的 Java,所以第一步是确认java -version可用,并记下java的绝对路径。
# 确认 Java 版本 java -version # 查看实际 java 二进制路径 which java拿到路径后,编辑conf/wrapper.conf。找到wrapper.java.command,如果它默认是java,最好改成绝对路径,否则bin/mycat start时会因为 PATH 环境变量不一致而找不到 JVM。内存参数也要在这里调:wrapper.java.initmemory是初始堆,wrapper.java.maxmemory是最大堆。对于 8G 内存的机器,我习惯把初始堆设为 512M,最大堆设为 2048M;超过 2048M 反而容易因为 Full GC 暂停过长导致 Wrapper 误判卡死。
# conf/wrapper.conf 关键参数 wrapper.java.command=/usr/local/jdk1.8.0_202/bin/java wrapper.java.initmemory=512 wrapper.java.maxmemory=2048注意wrapper.java.initmemory的单位是 MB,直接写数字就行,不要写512m或512M,否则 Wrapper 解析数字时会抛异常。这是我第一次部署时踩过的坑:照着网上博客在数字后面加了个m,结果Unable to start JVM。另外wrapper.java.classpath通常已经由模板写好了,不需要动,它会自动加载../lib/*.jar。
3.2 初始化数据库和配置 schema:先建库再配 MyCat
MyCat2 是一个中间层,它不存储数据,所有数据都在后端 MySQL 实例上。所以在启动 MyCat 之前,要先在后端 MySQL 里把物理库和表建好,然后再告诉 MyCat:哪个逻辑库对应哪个物理库、哪张表要走分片。顺序反了的话,MyCat 能启动但执行 SQL 时会报Table doesn't exist,而且这个错误不会出现在启动日志里,只会在客户端连接时报。
-- 在后端 MySQL 执行,创建两个物理库 CREATE DATABASE `db_0` DEFAULT CHARACTER SET utf8mb4; CREATE DATABASE `db_1` DEFAULT CHARACTER SET utf8mb4; -- 在每个库中建相同的表结构 CREATE TABLE `db_0`.`t_user` ( `id` bigint NOT NULL, `name` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB; CREATE TABLE `db_1`.`t_user` ( `id` bigint NOT NULL, `name` varchar(64) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB;建好物理库后,进入conf/datasources,新建数据源文件。MyCat2 的数据源配置是每个文件对应一个物理连接池,文件名氛围prototypeDs.datasource.json这种格式。下面是一个最小化的 JDBC 数据源配置:
{ "name": "ds_0", "dbType": "mysql", "type": "JDBC", "url": "jdbc:mysql://127.0.0.1:3306/db_0?useSSL=false&characterEncoding=utf8", "user": "root", "password": "123456", "maxCon": 100, "minCon": 1, "weight": 1, "instanceType": "READ_WRITE" }这个 JSON 里的name是连接池唯一标识,后续 cluster 和 schema 都要引用它;instanceType设为READ_WRITE表示这个数据源可以承担读写;如果做读写分离,只读实例要设为READ。maxCon是最大连接数,按后端 MySQL 的max_connections调整,minCon是预热连接数。模板里的conf/datasources目录下通常会有一个prototypeDs示例,我建议直接复制它再改name和url,不要从零手写,字段容易漏。
接着配置逻辑库。在conf/schemas目录下新建对应逻辑库的 schema 文件:
{ "schemaName": "mydb", "targetName": "ds_0" }schemaName是你给业务方看的数据库名,targetName指向刚才的数据源名。这是最简单的一库一映射,MyCat2 会把对mydb的所有 SQL 路由到ds_0对应的连接池。到这里,最小配置已经具备可启动性。
3.3 启动 mycat 并验证端口和状态
配置完成后,回到模板根目录启动。第一次启动建议在前台跑一次bin/mycat console,这样能直接看到 JVM 输出的错误信息,而不是被 Wrapper 吞到文件里。确认没问题后再用bin/mycat start转后台。
cd /opt/mycat2 # 前台调试启动,终端会直接打日志 bin/mycat console # 或者直接后台启动 bin/mycat start # 查看进程状态 bin/mycat statusbin/mycat console会抢占终端,看到类似MyCAT Server startup successfully的日志后,按Ctrl+C停掉,再执行bin/mycat start让它在后台跑。status命令如果返回running (pid: 12345),说明 Wrapper 已成功拉起 JVM。接下来用 MySQL 客户端验证端口:
mysql -h127.0.0.1 -P8066 -uroot -p123456注意用户名和密码要对应conf/users目录下配置的用户文件。连接成功后执行:
SHOW DATABASES;如果能看到你配置的mydb逻辑库,那么模板的“解压 → 配置 → 启动 → 连接”链路已经打通。如果SHOW DATABASES为空或者报权限错误,去conf/users下检查用户配置的 schema 授权范围。
4. 读写分离与分片配置实战:server.json、datasource、cluster 的关系
4.1 数据源配置:从后端 MySQL 到 MyCat 的逻辑映射
你可能会问:直接让 MyCat 连接 MySQL 不就行了吗?为什么还要拆出 datasource、cluster、schema 三层?因为 MyCat 需要知道后端有哪些实例、哪些是可写的、哪些是只读的、读写怎么分。datasources是“点”,每个文件代表一个物理连接池;clusters是“线”,把多个数据源串成一组,定义读写策略;schemas是“面”,把逻辑库映射到某个 cluster 或 datasource 上。
最开始用模板时,我把所有库都配成了一个READ_WRITE数据源,读写分离一直没生效。后来才发现,读写分离的前提是clusters目录里配一个主从 cluster,主节点用READ_WRITE或写专用,从节点用READ。MyCat2 的 cluster 配置里有两个关键字段:masters和replicas。masters列表里放可写数据源的name,replicas列表里放只读数据源的name。
{ "clusterName": "cluster_0", "masters": ["ds_master"], "replicas": ["ds_slave1", "ds_slave2"], "readBalanceType": "BALANCE_ALL", "writeBalanceType": "BALANCE_ALL", "readType": "DEFAULT" }readBalanceType控制读请求如何在多个 replica 间分配,BALANCE_ALL表示所有可用的只读节点参与负载均衡;writeBalanceType对 master 列表做同样的均衡。如果只有一个主节点,writeBalanceType设不设都无所谓。readType一般保持DEFAULT,表示读请求按路由规则决定是否落从库。这样配置后,MyCat 对SELECT会优先路由到ds_slave1或ds_slave2,对INSERT/UPDATE/DELETE会路由到ds_master。
4.2 分片规则与 cluster:让 SQL 路由到正确的分片
分片是 MyCat2 最核心的能力,但模板不会给你提供现成的分片策略,它只提供配置载体。你要在schemas的逻辑表定义里指定分片键和分片算法。这里以最常见的取模分片为例:假设t_user表按id分到两个库,那么 schema 文件要改成指向一个 cluster,而不是单一数据源。
{ "schemaName": "mydb", "targetName": "cluster_0", "shardingTables": { "t_user": { "sqlMaxLimit": 100, "partition": { "algorithm": "mod_hash", "column": "id", "shardingTargets": ["ds_0", "ds_1"] } } } }这里的shardingTargets列出了t_user的数据分片,mod_hash按id取模决定行落在哪个数据源。MyCat2 根据这个配置把 SQL 改写后发往对应后端。原理上,MyCat2 会先解析 SQL,从 WHERE 条件里提取分片键的值,计算出目标分片,然后把 SQL 路由过去;如果 WHERE 没有分片键,它就只能把 SQL 广播到全部分片,再把结果合并。所以分片键的选择直接影响查询性能,必须把它放到高频查询的过滤条件里。
这里有个容易混淆的概念:clusters管读写,schemas管分片。两者并不冲突。分片表的数据可以分布在一组读写集群上,非分片表直接挂在某个 cluster 或 datasource 上。模板的conf/clusters下通常会有一个prototype.cluster.json,它就是给非分片表用的默认集群。我一般把非分片表放在normalTables,分片表放在shardingTables,避免所有表都要走一遍分片计算。
4.3 用户权限与 SQL 限制:users 目录中的安全配置
conf/users目录下每个 JSON 定义一个 MyCat 登录账号,对应 1.x 的<user>标签。最小配置如下:
{ "username": "root", "password": "123456", "ip": "127.0.0.1", "dialect": "mysql", "poolSize": 10 }ip如果不写,默认允许所有 IP 连接,生产环境一定不要留空。poolSize是当前账号到 MyCat 的并发连接数,和maxCon不同,maxCon是 MyCat 到后端数据源的连接数,poolSize是客户端到 MyCat 的连接数。如果业务有数百个应用实例同时连 MyCat,poolSize设 10 会导致连接排队,常见现象是客户端报TooManyConnections,但 MyCat 本身没挂。
users 和 schema 的权限关系也需要留意。MyCat2 会检查该用户是否对某个逻辑库有访问权,如果schemas里配置了mydb,但用户 JSON 里没有关联字段,那SHOW DATABASES可能看不到它。不同版本对权限关联的写法有差异,我习惯在用户 JSON 里显式声明允许访问的 schema 列表,字段名为schemas。这样做虽然会多几行配置,但能在误操作时保住后端数据源不被无关用户探测到。
{ "username": "app_user", "password": "app_pass", "ip": "10.10.%", "dialect": "mysql", "poolSize": 20, "schemas": ["mydb"] }ip字段支持 MySQL 风格的通配符%,比写死单个 IP 灵活。注意dialect必须和后端 MySQL 一致,如果填成postgresql,MyCat2 会用 PostgreSQL 协议解析客户端请求,直接握手失败。
5. 避坑 / 常见问题:MyCat2 安装模板使用中的五个典型故障
5.1 启动报错 wrapper | Unable to start JVM:内存参数写法错误
现象:bin/mycat start后终端没有输出,但logs/wrapper.log里出现wrapper | Unable to start JVM。
原因:wrapper.conf中wrapper.java.initmemory或wrapper.java.maxmemory写了带单位的值,比如1024m,或者数值超过机器剩余内存。Wrapper 对这个参数要求纯数字,单位由 Wrapper 自己识别为 MB,带了字母后解析失败,JVM 无法启动。
解决:打开conf/wrapper.conf,把内存参数改成纯数字,比如512和2048。改完执行bin/mycat restart。如果还报错,用free -m看机器可用内存,把wrapper.java.maxmemory调低到物理内存的三分之一以内。
5.2 bin/mycat start 后进程秒退,logs 里没有任何 Java 堆栈
现象:执行bin/mycat start后看status显示没有进程,logs/wrapper.log只有一两条记录,没有异常堆栈。
原因:最常见的是找不到 Java 命令。模板里的wrapper.java.command默认值是java,它依赖JAVA_HOME环境变量。如果你通过 systemd 或 cron 启动 MyCat,环境变量可能没有加载,Wrapper 找不到java,进程直接退出。
解决:在wrapper.conf里把wrapper.java.command硬编码为绝对路径,比如/usr/local/jdk1.8.0_202/bin/java。我不建议只在/etc/profile里 exportJAVA_HOME,因为非交互 shell 不一定读它。改完后执行bin/mycat start,再bin/mycat status确认。
5.3 3306 端口被占:MyCat2 默认端口是 8066 还是 3306
现象:客户端连接时误用-P3306,连上了本机 MySQL 而不是 MyCat,或者反过来 MyCat 后端连接到了 3306 端口上的 MyCat 自己,导致循环连接。
原因:MyCat2 模板的server.json默认监听 8066,不是 3306。很多从 MySQL 直接迁移的同事下意识用 3306 连接,结果连到了后端 MySQL;而配置 datasource 时又把 MyCat 自己的 8066 当成 MySQL 端口,形成自连。
解决:客户端连接 MyCat 时明确使用-P8066,并在conf/datasources中确认所有url指向真正的后端 MySQL 端口。如果业务要求客户端用 3306 端口访问 MyCat,可以修改server.json的port为 3306,但必须同时停掉本机 MySQL,否则端口冲突。
5.4 连接 MyCat 报 Unknown database 'test':schema 目录里没有对应库
现象:mysql -h127.0.0.1 -P8066 -uroot -p能成功登录,但执行USE test时报Unknown database 'test'。
原因:MyCat2 的逻辑库不是从后端 MySQL 自动同步的。后端 MySQL 里CREATE DATABASE test后,MyCat2 不会感知,除非你在conf/schemas目录下为该库创建了对应的 schema JSON 文件。
解决:在conf/schemas目录新建test.schema.json,内容至少包含schemaName和targetName,后端物理库真实存在即可。改完不需要重启 MyCat,它会定期加载配置文件;如果不生效,执行bin/mycat restart。从那以后,我每次建库都会先在 conf 目录里同步创建 schema 文件,再通知业务方使用,否则“库不存在”的报错会让人误以为数据库连接有问题。
5.5 分片查询结果错乱:分片键没进 WHERE 或者用了不支持的函数
现象:执行SELECT * FROM t_user返回的数据重复或者缺失,插入数据后查不到;有些带max(id)、order by的 SQL 结果与预期不一致。
原因:分片表的路由依赖 WHERE 条件中的分片键。没有分片键时,MyCat2 会把 SQL 广播到全部分片,再对结果做合并。部分聚合函数和排序在合并阶段可能无法正确处理,导致结果错乱。另外,如果分片键字段类型不匹配,比如字符串id和整数id混用,取模结果也会乱。
解决:要求业务 SQL 必须带分片键等值条件,例如WHERE id = 100或WHERE id IN (100, 101)。对于必须全表扫描的场景,把表改成非分片表,或者使用 MyCat2 的全局表机制,让每张分片都保留完整副本,再走广播路由。我在模板初始化时就会在schemas的normalTables里声明这类小表,避免后患。
6. 验证安装的进阶套路:用 explain 和状态表确认路由与读写分离生效
安装模板本身不生产业务数据,但它把所有验证手段都留好了:logs目录记录执行过程,conf目录让配置可追踪。我最常用的一套验证方法是:先看进程,再看端口,最后用 MyCat 自己的 explain 能力检查 SQL 路由。
6.1 用 SQL 的 explain 查看路由结果
MyCat2 支持在 SQL 前加explain来输出路由计划,而不是 MySQL 那种传统的执行计划。比如:
EXPLAIN SELECT * FROM mydb.t_user WHERE id = 1;返回结果会显示这条 SQL 被路由到了哪个数据源和目标分片。如果id = 1按mod_hash应该落在ds_0,但 explain 显示目标为ds_1,说明分片算法或分片键类型有问题,需要立刻检查。我一般把这个输出和业务日志里的实际慢查询做对照,很快就能定位是否发生了不必要的全分片广播。
6.2 通过状态命令检查读写分离
连接 MyCat 后执行:
SHOW @@datasource;这个命令会列出所有后端数据源的状态,包括连接数、负载、心跳是否正常。如果replicas里配了从库,但SHOW @@datasource中完全看不到该数据源,说明 cluster 配置没有被加载,读请求永远不会落到从库。还有一个技巧:在 MySQL 主库和从库分别执行SHOW PROCESSLIST,发一些查询,观察哪个实例的Command多为Query。写只到主库是正常,读全到主库则要检查clusters配置里的readBalanceType是否为BALANCE_ALL。
实际排查时,我会先把wrapper.conf改好,再启动,然后按顺序执行bin/mycat status、mysql -h127.0.0.1 -P8066 -uroot -p、SHOW DATABASES、EXPLAIN这几步。如果任何一步没达到预期,优先去看logs/mycat.log里最近 50 行,里面的路由错误或配置加载错误通常比终端提示更详细。有一次我因为datasources目录下残留了一个旧的.json文件,里面用户密码和集群中引用不一致,导致 MyCat 启动时加载了这个文件,看起来是“核对了配置”实际上用了脏数据。从那以后,我每次修改任何配置前都强制先备份整个conf目录,改完重启后跑一遍上面的验证流程,确认无误才交给业务同事。希望帮到你。
本文还有配套的精品资源,点击获取