
简介本资源为 Mycat2 分布式数据库中间件的基础安装包面向需要在本地或服务器上搭建数据库分片与读写分离架构的 Java 开发者和运维人员用于解决单机数据库在高并发、大数据量场景下的扩展性瓶颈。压缩包共 51 个文件约 1.2MB以 sql 初始化脚本、so/jnilib/a/dll 等多平台本地库、json 与 xml 配置、bat/mycat 启动脚本及 jar 依赖为主覆盖 Windows、Linux、macOS、AIX、Solaris 等系统的 wrapper 适配文件解压后按需修改 schemas、datasources、server 等配置即可启动服务。已有 1072 人学习下载可作为理解数据分片规则、SQL 路由、读写分离与动态扩缩容的实践起点包内附带的示例 SQL 与多平台启动脚本也便于对照排查环境问题、快速验证部署流程。1. 拿到 mycat2 基础安装包先别急着 start单体 MySQL 撑到某个量级最先出问题的往往不是 SQL 写得烂而是单表几千万行之后加个索引要锁半小时、备份窗口越来越长、主从延迟一抖业务就报警。这时候团队通常会想到分库分表中间件mycat2 基础安装包就是干这个的它是一个说 MySQL 协议的代理层应用连它和连 MySQL 几乎没有区别分片路由、读写分离、全局表这些逻辑都在代理这一层做掉业务侧的 JDBC 连接串改个端口就能接上去。它适合谁手上已经有一套能跑的 MySQL、又不愿意为了分库分表去改业务代码里那堆 SQL 和连接的团队。不适合谁指望着装完就自动分片的人——mycat2 的元数据是要你自己一条条配出来的数据源、集群、逻辑库、分片表四层东西少一层就跑不通。下面按我实际拆包的顺序写先看包结构和启动链路再讲三层配置怎么串然后是分片表落地和那五个必踩的坑。2. 解压到第一次连上 8066包结构与启动链路拿到包之后第一件事不是敲 start而是把目录看一遍。mycat2 的运行态很简单一个 Java 进程读 conf 下的元数据对外开一个 MySQL 协议端口把 SQL 转发到后面真实的 MySQL 实例。所以它出问题的地方也就那么几处——JDK 版本、conf 里的 JSON 格式、端口占用、以及后面物理库连不连得上。把这几处的检查顺序固定下来后面 debug 能省掉一大半时间。2.1 四个目录各管什么解压后基本就是 bin、conf、lib、logs 四个目录其中 conf 是你以后动得最多的地方lib 基本不动logs 是每次启动失败的第一站。目录/文件作用什么时候动它bin/启停脚本Linux 下是 mycatWindows 下是 mycat.bat调 JVM 堆大小、换启动用户conf/server.yaml服务端口、线程数这类进程级参数改端口、压测时调线程池conf/datasources/每个物理 MySQL 一个 json加实例、改连接池大小conf/clusters/主从组写节点和读节点列表加从库、调读策略conf/schemas/逻辑库和逻辑表元数据加库、加分片表conf/users/连接代理用的账号上线前必须改默认密码lib/依赖 jar 和自带的算法类换 MySQL 驱动、扩分片算法logs/mycat.log 及滚动历史启动失败、路由异常一个容易忽略的点conf 下的这些 json 不是参考配置是运行时的唯一真相。你在客户端里用命令动态建出来的数据源、集群、逻辑库最终也是落到这几个目录里。所以千万别一边手改文件、一边用命令建同名对象两边打架的时候 reload 会给你一个很难看懂的错误。2.2 JDK、启动脚本与端口mycat2 是 Java 进程JDK 版本不匹配的典型表现是进程起来几秒就没了日志里只有一行看不懂的异常。所以第一步永远是确认 java 版本再解压。# 1. 确认 JDK8 或 11 是主流验证过的组合别在第一次跑通前折腾太新的版本 java -version # 2. 解压到固定目录路径里不要带空格和中文 mkdir -p /opt/mycat2 unzip mycat2-basic.zip -d /opt/mycat2 cd /opt/mycat2 # 3. 先看启动脚本里最终拼出来的 java 命令堆大小和 classpath 都在这 sed -n 1,80p bin/mycat # 4. 启动并查状态 bin/mycat start bin/mycat status # 5. 确认端口真的监听了status 说 RUNNING 不代表端口起来了 ss -lntp | grep 8066这段里第 3 步是关键。启动脚本本质上就是拼一条java -cp ... 主类的命令行堆大小、GC 参数、配置文件路径都写在里面。第一次跑不通的时候把这条命令手工敲一遍去掉后台重定向异常会直接打在终端上比翻日志快得多。堆大小我一般从 2g 起步代理层本身不存数据内存主要花在连接缓冲和 SQL 解析上给太大反而拖长 GC 停顿。参数上要盯住两个一是-Xmx二是 server.yaml 里的监听地址和端口。默认端口是 8066如果这台机器上已经有别的实例改 server.yaml 比改脚本靠谱。启动脚本报端口已被占用的时候用ss -lntp | grep 8066找到占用进程别急着 kill先确认是不是上一次没停干净的自己。启动失败时不要从头读日志几万行读不完# 只看最后 80 行异常栈的根因通常在最后 tail -n 80 logs/mycat.log # 直接把错误行捞出来Caused by 才是真正的根因 grep -nE ERROR|Exception|Caused by logs/mycat.log | tail -n 30如果 logs 下的 mycat.log 是空的去看同目录下启动脚本重定向产生的那个控制台日志。这种情况一般是 JVM 在加载类阶段就挂了业务日志框架还没来得及初始化所以业务日志里什么都看不到——这也是为什么第 3 步手工执行那么重要。2.3 用 mysql 客户端验证代理真的活了进程起来、端口监听只能说明它活着不能说明元数据是好的。真正的验收标准是能用 MySQL 客户端连上并且能看到数据源列表。# 客户端版本别太老太老的可能在握手阶段就断连 mysql -h127.0.0.1 -P8066 -uroot -p123456-- 先看库列表确认连的是代理而不是背后某个物理库 show databases; -- 再看数据源这是管理命令写在 /* */ 注释里不是普通 SQL /* mycat:showDataSources{} */; /* mycat:showClusters{} */; /* mycat:showSchemas{} */;这三条命令返回的是代理内存里的元数据快照能正常返回就说明配置文件解析没问题、内置的 prototype 数据源至少加载成功了。如果show databases只有一两个库、和你预期的对不上问题一定在 conf/schemas 下不在网络。参数上注意两点默认账号密码在 conf/users 下的 user json 里明文写着上线前必须改掉并且要把这个账号能访问的逻辑库列表一起收窄端口 8066 是服务端口管理命令走的是同一个连接不需要另开管理端口这一点和很多老版本中间件不一样别去找 9066。3. 三层配置模型数据源、集群、逻辑库怎么串起来mycat2 的配置之所以让新手懵是因为它把一台物理库和一个逻辑库彻底拆开了。你要先在数据源层描述清楚每台真实的 MySQL 在哪、账号是什么、连接池多大再在集群层把若干数据源组成一个主从组说明谁是写、谁是读最后在逻辑库层给应用一个它认识的库名并挂上这个库的表元数据。三层缺一层SQL 就没有完整的路由路径。3.1 一条 SQL 到物理库要过几道关应用连上来的时候带的是逻辑库名和用户名代理先按 users 里的配置校验账号、确认这个账号能访问哪些逻辑库然后按逻辑库找到它绑定的集群再按集群找到写节点和读节点列表最后根据 SQL 是读还是写、表是不是分片表决定发到哪台物理库的哪个库名上。这条链路里任何一环名字对不上报错都长得很像——基本就是Unknown database或者连接被拒。所以配的时候有个笨办法特别有效三个名字数据源名、集群名、逻辑库名提前写在纸上全程只用这一套命名别一会儿 dw0 一会儿 ds0。我见过不止一次因为手抖把 replicas 里写了个不存在的数据源名折腾半天以为是网络问题。3.2 数据源一个 json 就是一台物理 MySQL数据源配置放在 conf/datasources 下一个文件一个实例。下面是骨架字段名以你包里自带的样例文件为准不同小版本可能有增删。{ name: dw0, type: JDBC, dbType: mysql, url: jdbc:mysql://127.0.0.1:3306/db1?useSSLfalsecharacterEncodingutf8serverTimezoneAsia/Shanghai, user: root, password: 123456, minCon: 2, maxCon: 50, maxConnectTimeout: 3000, maxRetryCount: 3, instanceType: READ_WRITE, weight: 0 }这个文件里真正需要你判断的只有几个字段。name是全局唯一的引用名后面集群里写的就是它url里一定要带serverTimezone否则时间字段跨时区会偏 8 小时这个坑排查起来极其费劲minCon和maxCon决定这个实例上常驻和峰值连接数把它乘以实例数、再乘以集群数就是你的 MySQL 端要扛的总连接数max_connections不够就会在压测时突然大面积超时maxConnectTimeout是建连超时内网 3000 毫秒够用跨机房要放大maxRetryCount是建连失败重试次数从库不稳的时候它会救你一命但也会让错误暴露得慢一点。instanceType用来标记这个实例的角色weight是读流量权重多从库分摊读的时候用得上。其余字段保持样例默认值就行别一上来就全改一遍——出问题的时候你不知道是哪个字段改坏的。3.3 集群masters 和 replicas 决定读写去哪集群层是很多人第一次用会写错的地方。masters里放的是写节点replicas里放的是读节点两个列表里填的都是数据源的name不是主机名。{ name: c0, clusterType: MASTER_SLAVE, masters: [dw0], replicas: [dw1, dw2], readBalanceType: BALANCE_ALL, switchType: SWITCH, heartbeat: { replicas: SELECT 1, timeout: 1000 } }参数上有几个边界值得说清楚。masters只有一个元素时就是标准主从如果放多个它表达的是多个写分片路由会再按分片规则分配别把它当成双主同时写。readBalanceType控制读请求怎么分摊到 replicas全都可用的策略吞吐最好但对主从延迟最敏感如果业务里有写完立刻查的场景要么把读策略调保守要么让这类查询走事务别硬扛。switchType是主库挂了要不要自动切测试环境建议关掉免得排查问题时主从角色自己变来变去日志都看不懂。heartbeat是探活语句和超时探活语句别写太重的 SQLSELECT 1足够。3.4 逻辑库应用看到的那个库逻辑库是应用侧唯一感知到的一层名字最好和原来的物理库名保持一致这样老代码里的库名不用动。{ schemaName: shop, targetName: c0, normalTables: {}, globalTables: {}, shardingTables: {}, customTables: {} }targetName指向集群名。下面四个空对象是四类表的容器用哪类表就往哪类里填normalTables是不分片的普通表globalTables是每个节点都存一份全量数据的字典表省份、类目、配置项这种shardingTables是分片表customTables是你要自己接管路由的表。新手最常见的误操作是把所有表都塞进shardingTables结果字典表被切得七零八落join 的时候疯狂跨节点。3.5 用命令在线建三条 SQL 顶三个文件除了改文件也可以在客户端里直接建适合临时加一个从库验证效果。命令写在/* */注释里末尾的分号不能少。-- 建数据源字段和 json 文件里的一一对应 /* mycat:createDataSource{ name:dw3, url:jdbc:mysql://127.0.0.1:3307/db1?useSSLfalsecharacterEncodingutf8serverTimezoneAsia/Shanghai, user:root, password:123456, minCon:2, maxCon:50 } */; -- 建集群只有一个写节点时replicas 可以留空 /* mycat:createCluster{name:c1,masters:[dw3]} */; -- 建逻辑库挂到刚建的集群上 /* mycat:createSchema{schemaName:shop2,targetName:c1} */; -- 让内存里的元数据重新加载一遍 /* mycat:reload{} */;逻辑上要理解一件事这几条命令改的是运行态元数据同时会往 conf 目录写对应文件所以它和手改文件是同一个数据源别两边同时改同一个对象。参数上和配置文件完全一致唯一要注意的是 JSON 必须写在一行内或者保证注释完整透传——有的客户端会帮你把注释删掉一删命令就退化成普通 SQL报一个莫名其妙的语法错误。4. 分片表落地shardingTables 骨架、分片键选型与落位验证单库单表跑通之后真正的工作量在分片表上。分片表的本质是一条逻辑表名 一套路由函数 一组物理节点三者必须严格对齐节点数要和路由函数的参数匹配建表语句要和物理库里的实际结构一致。这两条对不上表现是数据能插进去但查不出来或者干脆建表就报错。4.1 分片表在配置里的骨架分片表挂在逻辑库 json 的shardingTables下面键是逻辑表名。shardingTables: { order_detail: { createTableSQL: CREATE TABLE order_detail (id bigint NOT NULL, order_id bigint NOT NULL, user_id bigint NOT NULL, amount decimal(12,2) DEFAULT NULL, PRIMARY KEY (id), KEY idx_user (user_id)) ENGINEInnoDB DEFAULT CHARSETutf8mb4, function: { clazz: io.mycat.router.mycat1xfunction.PartitionByLong, name: partitionByLong, properties: { partitionCount: 2, partitionLength: 2 } }, shardingNodes: [c0_0.order_detail, c0_1.order_detail] } }四个字段各有分工。createTableSQL是建表模板代理在初始化时按它去物理库建表所以它必须和你线上真实表结构逐字一致包括字符集和索引——线上表加了个字段忘了同步这里重启之后新节点建出来的表就少一列。function.clazz是路由算法类从 lib 目录里包里自带的那批io.mycat.router.开头的类里选除非你非常清楚自己在做什么别自己写一个。function.properties的键名跟着算法走取模类算法一般要分片键列名和分片数范围类算法一般要列名和区间边界具体以包里样例为准。shardingNodes的写法要特别注意它是节点名.表名而节点名的形式取决于你的集群怎么定义单主从集群里直接写数据源名dw0.order_detail多写节点的分片集群里是集群名加序号c0_0.order_detail、c0_1.order_detail。这两种写法在不同小版本、不同集群形态下不一样最稳的做法是打开 conf/schemas 下自带的样例文件照着它的形式写别凭记忆敲。4.2 分片键和算法怎么选选算法之前先看查询长什么样别看数据长什么样。分片键必须是绝大多数查询都会带上的那个条件否则每次查询都要广播到所有分片代理层的优势直接归零。算法类型适合的分片键扩容代价典型翻车点取模/哈希基数高、写入分散如 user_id、order_id高改分片数要整体重分布分片键为 NULL 或字符串大小写不一致落到默认节点范围/区间有时间语义如月份、号段低加区间即可冷热不均新数据全压最后一个分片自定义节点数会频繁变动的场景中算法类改完 reload存量数据路由对不上我自己总结的三条硬标准第一分片键基数要足够大性别、状态这种字段分片等于没分第二核心查询的 where 里必须带分片键报表类全表扫描的查询要单独规划走不走代理第三分片键一旦写入就不要更新跨分片改分片键等于一条 update 变两条跨库事务代理层帮不了你。三条都满足再动手配比配完再改省事得多。4.3 三步验证数据真的落对了配置写完reload 之后必须验证别信没报错就是对的。验证分三步从代理侧写数据、从代理侧读回来、再到每个物理库对数。# 第一步和第二步从代理写入并读回走的是应用的视角 mysql -h127.0.0.1 -P8066 -uroot -p123456 shop -e insert into order_detail(id, order_id, user_id, amount) values (1,1001,1,9.90),(2,1002,2,19.90),(3,1003,3,29.90); select count(*) as proxy_total from order_detail;# 第三步到每个物理库分别数一遍两边的和要等于代理上看到的总数 for p in 3306 3307; do mysql -h127.0.0.1 -P$p -uroot -p123456 -N -e \ select $p as port, count(*) from db1.order_detail; done第一段的逻辑是确认代理层的读写链路是通的proxy_total是代理聚合后的结果。第二段的关键在于分布而不是总数如果两个物理库各 3 行、但某个库里出现了本该属于另一个分片的分片键说明路由函数参数写错了如果总数对、但其中一个是 0说明shardingNodes只写了一个节点或者分片数配成了 1。这种错误不会报异常只会在数据量涨起来之后以某个库磁盘爆了的形式暴露所以每次改分片配置都要跑一遍。4.4 哪些表不该分片字典表、配置表、类目表这类数据量小、读多写少、又经常被 join 的表放globalTables里每个节点存一份全量join 就在本地完成。业务主表和它的明细表如果总是按同一个维度查订单和订单明细都按 user_id 查把两张表的shardingNodes一一对齐保证同一份数据落在同一个节点join 就不会跨库。反过来任何需要跨分片聚合的查询都要提前想清楚count(*)、sum、深分页、多表 join在代理层的代价远高于单库。这些查询要么在业务侧改成按分片键查、要么单独走一条不经过代理的报表链路别指望中间件替你解决。5. 避坑与排查五个高频翻车现场下面这五条是我自己在不同环境里反复遇到的按现象 → 原因 → 解决写遇到问题时可以按顺序对照。5.1 启动本文还有配套的精品资源点击获取