资讯详情

资讯详情

MyCat 2.x 生产级分库分表实战:从零配置到故障定位

简介本资源是一套面向Java后端开发者与数据库架构师的Mycat分布式数据库中间件系统化教程聚焦从零基础入门到生产级精通重点解决高并发、大数据量场景下的分库分表、读写分离与高可用架构难题。压缩包共2个文件1个HTML文档1个TXT说明总大小仅6KB轻量便携HTML文件承载完整教程正文涵盖Mycat核心原理、Server/DataNode/Schema/Rule等关键概念、server.xml与schema.xml配置详解、哈希/范围分片策略对比、XA事务处理机制、多节点高可用部署及性能调优要点TXT文件提供配套学习指引与延伸资源索引。内容结构清晰理论结合电商、社交等典型业务场景同步对比ShardingSphere、Cobar等主流中间件助力读者建立选型判断力与落地实施能力。目前已有453人学习下载适合希望快速掌握分布式数据库中间件实战能力的中高级开发人员。1. MyCat 是什么不是数据库也不是中间件“玩具”而是生产级分库分表路由中枢MyCat 入门到精通教程——这个标题背后藏着一个被严重低估的现实大量团队在业务增长到单库瓶颈时第一反应是换 PostgreSQL、上 TiDB、堆读写分离却忽略了 MyCat 这个已在金融、电商、政务类系统中稳定运行超八年、支撑日均亿级事务的开源数据库中间层。它不替代 MySQL也不伪装成 NewSQL它的核心价值是用 SQL 兼容性换分片自由度你写的还是SELECT * FROM order WHERE user_id ?MyCat 在底层自动路由到order_001表所在的物理库甚至跨机房做读写分离与故障转移。这不是“代理层”而是带 SQL 解析、执行计划重写、分布式事务协调XA/Seata 集成、全局序列、ER 分片、热数据隔离能力的数据库流量调度中心。适合谁适合已有成熟 MySQL 架构、不愿重写 DAO 层、又急需横向扩展的中大型项目不适合纯新项目可直接选 TiDB 或 Vitess也不适合单表百万以下的小系统加索引缓存更轻量。本教程不讲“安装就完事”的玩具式操作而是从真实压测翻车现场出发带你把 MyCat 跑进生产环境——包括为什么schema.xml里table的dataNode顺序会影响 JOIN 性能为什么server.xml中processors值设为 CPU 核数×2 反而拖慢吞吐以及最关键的如何用mycat.log和show sql.execute定位一条 SQL 是被广播了、路由错了、还是卡在连接池。2. 从零启动用最小配置跑通分片查询与写入闭环2.1 下载、解压与基础目录结构认知MyCat 官方已停止维护旧版 1.x当前主力版本为MyCat 2.x注意不是 MyCat 2.0而是持续迭代的 2.x 系列最新稳定版为 2.3.0。它不再依赖 JDK 8最低要求 JDK 11且彻底重构了网络层与执行引擎。下载地址统一为 GitHub Release 页面搜索MyCat-Server官方组织避免使用镜像站或第三方打包版——曾有团队因某镜像站混入含 Log4j 漏洞的旧包导致线上审计失败。# 推荐方式用 wget 直接拉取官方 Release以 2.3.0 为例 wget https://github.com/MyCatApache/MyCat2/releases/download/2.3.0/Mycat2-2.3.0-linux.tar.gz tar -xzf Mycat2-2.3.0-linux.tar.gz cd mycat2解压后关键目录说明非默认路径需在conf/mycat.properties中显式指定目录作用是否可改conf/所有核心配置mycat.properties,schema.json,router.json,datasource.json✅ 可通过-Dmycat.conf.dir指定logs/日志输出默认按天滚动mycat.log是主诊断日志✅ 可配logback-spring.xmllib/内置 JDBC 驱动MySQL 8.0、Netty、Fastjson 等依赖❌ 不建议手动替换bin/启动脚本start.sh前台、startup.sh后台、stop.sh✅ 可修改 JVM 参数提示MyCat 2.x废弃了 MyCat 1.x 的schema.xmlrule.xmlserver.xml三文件模式全部合并为 JSON 结构化配置语义更清晰但迁移需重写。别试图复制旧版配置——会直接启动失败。2.2 三步完成最小可用分片环境建库、配节点、跑 SQL我们以最典型的「用户订单」场景为例user表按id分片到 2 个 MySQL 实例order表按user_id分片并绑定userER 分片确保JOIN user ON order.user_id user.id不跨库。第一步准备两个物理 MySQL 实例假设 IP 为 192.168.1.10:3306 和 192.168.1.11:3306-- 在两台 MySQL 上分别执行库名必须一致MyCat 会自动创建同名逻辑库 CREATE DATABASE IF NOT EXISTS mycat_demo; USE mycat_demo; CREATE TABLE user ( id BIGINT PRIMARY KEY, name VARCHAR(64), city VARCHAR(32) ); CREATE TABLE order ( id BIGINT PRIMARY KEY, user_id BIGINT NOT NULL, amount DECIMAL(10,2), create_time DATETIME );第二步配置conf/datasource.json—— 定义物理数据源{ dataSources: [ { name: dn1, url: jdbc:mysql://192.168.1.10:3306/mycat_demo?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue, username: root, password: 123456, maxPoolSize: 200, minPoolSize: 20, connectionTimeout: 30000 }, { name: dn2, url: jdbc:mysql://192.168.1.11:3306/mycat_demo?useSSLfalseserverTimezoneAsia/ShanghaiallowPublicKeyRetrievaltrue, username: root, password: 123456, maxPoolSize: 200, minPoolSize: 20, connectionTimeout: 30000 } ] }参数说明maxPoolSize不宜设过高超过 300 易触发 MySQLmax_connections限制connectionTimeout必须小于 MySQL 的wait_timeout默认 28800 秒否则空闲连接被 MySQL 主动断开后 MyCat 不感知下次复用时报Connection closed。第三步配置conf/schema.json—— 定义逻辑库、分片规则与 ER 关系{ schemas: [ { name: TESTDB, tables: [ { name: user, type: global, // 全局表所有节点都存完整副本适合字典表 shardingNodes: [dn1, dn2] }, { name: order, shardingNodes: [dn1, dn2], shardingRule: { shardingColumn: user_id, shardingAlgorithm: mod-long } } ], shardingRules: [ { name: mod-long, type: hash, props: { count: 2 } } ] } ] }逻辑说明这里定义了一个名为TESTDB的逻辑库其中user表设为global类型全节点复制order表按user_id字段取模分片到dn1和dn2。mod-long算法表示对user_id做user_id % 2结果为 0 路由到dn1为 1 路由到dn2。注意shardingNodes数组顺序必须与datasource.json中dataSources的声明顺序严格一致否则分片错位第四步启动并验证# 启动首次启动会自动生成 conf/router.json 等文件 ./bin/startup.sh # 检查进程与端口默认监听 8066管理端口 9066 ps aux | grep mycat netstat -tuln | grep :8066 # 用 MySQL 客户端连接 MyCat不是连物理 MySQL mysql -h127.0.0.1 -P8066 -uroot -p123456 -DTESTDB此时执行INSERT INTO user(id, name, city) VALUES(1, Alice, Beijing); INSERT INTO order(id, user_id, amount, create_time) VALUES(1001, 1, 99.9, NOW()); SELECT u.name, o.amount FROM user u JOIN order o ON u.id o.user_id;若返回Alice, 99.9说明分片路由、ER 关联、JOIN 下推全部生效——最小闭环跑通。3. 分片策略深度解析何时用取模、何时用范围、ER 分片怎么不翻车3.1 三种主流分片算法的本质与适用边界MyCat 2.x 内置算法远不止mod-long其选择直接决定扩容成本与查询性能。我们对比三种高频场景算法类型配置示例适用场景扩容代价查询风险取模Hashcount: 4用户 ID、订单号等离散均匀 ID高需迁移 50% 数据WHERE id IN (1,2,3)可下推BETWEEN无法下推变广播范围RangemapFile: range-long-partition.txt时间字段如create_time、地区编码低新增分片节点即可WHERE create_time 2023-01-01可精准路由LIKE 2023%无法下推一致性哈希Consistent HashvirtualNodeCount: 160需频繁扩缩容的缓存型业务极低仅移动少量数据IN、BETWEEN均无法下推强制广播关键认知没有“最好”的算法只有“最不坏”的妥协。比如电商订单表若按order_id雪花 ID取模看似均匀但因 ID 生成有时间局部性会导致新订单集中写入单个节点形成热点。此时应改用user_id % 4order_id作为复合分片键或直接切时间范围。3.2 ER 分片让 JOIN 不跨库的核心机制与致命陷阱EREntity Relationship分片是 MyCat 区别于普通代理的核心能力它保证强关联的父子表如user←order的分片键值落在同一物理节点使JOIN、IN子查询、GROUP BY能下推执行而非全节点广播。配置schema.json中order表的shardingRule需显式声明erTable{ name: order, shardingNodes: [dn1, dn2], shardingRule: { shardingColumn: user_id, shardingAlgorithm: mod-long, erTable: user // 关键声明父表名 } }但 ER 分片有三个硬约束违反任一即失效父表必须是全局表type: global或与子表同分片规则→ 若user表也按id取模分片则user_id和user.id的分片结果可能不一致JOIN 仍跨库。子表shardingColumn值必须存在于父表主键中→order.user_id必须是user.id的有效值否则路由错乱。MyCat 不校验外键靠业务保证。INSERT 时必须同时提供父表分片键→ 插入order时若只写INSERT INTO order VALUES(1001, 1, ...)MyCat 能路由但若写INSERT INTO order(user_id, amount) SELECT id, 99.9 FROM user WHERE cityBeijing则因子查询未显式提供user_id值MyCat 无法确定目标节点报错Cant find sharding node for table order。血泪经验某次大促前压测发现JOIN查询 QPS 暴跌 70%排查发现user表被误配为sharding类型非 global导致所有order JOIN user变成全节点广播。回滚配置后恢复——ER 分片失效的第一迹象永远是慢查询日志里出现broadcast字样。3.3 全局序列解决分布式主键冲突的工业级方案MyCat 自带两种全局序列生成器本地文件localfile和数据库dbseq。生产环境必须用dbseq否则多 MyCat 实例间无法同步序列值。配置conf/sequence.json{ sequences: [ { name: GLOBAL_SEQ, type: dbseq, props: { dataSource: dn1, // 必须指向一个物理数据源 tableName: MYCAT_SEQUENCE, seqColumn: seq_value, increment: 100, minValue: 1 } } ] }并在物理 MySQL 的mycat_demo库中建表CREATE TABLE MYCAT_SEQUENCE ( name VARCHAR(64) PRIMARY KEY, seq_value BIGINT NOT NULL, increment INT NOT NULL DEFAULT 100, minValue BIGINT NOT NULL DEFAULT 1 ); INSERT INTO MYCAT_SEQUENCE VALUES(GLOBAL_SEQ, 1, 100, 1);使用时在schema.json的表定义中添加{ name: order, autoIncrement: true, sequence: GLOBAL_SEQ, ... }参数说明increment100表示每次从 DB 取 100 个号段缓存在 MyCat 内存中降低 DB 压力。若单实例 QPS 超 500建议调至1000但若 MyCat 频繁重启小 increment 会导致号段浪费。不要用 UUID 或雪花 ID 替代——MyCat 的INSERT ... SELECT LAST_INSERT_ID()语法依赖连续整数主键。4. 生产避坑指南5 个让团队加班到凌晨的真实问题与解法4.1 现象SELECT COUNT(*) FROM order执行超时mycat.log报timeout原因MyCat 对聚合函数COUNT,SUM,AVG默认走merge模式先向所有分片发SELECT COUNT(*)再在 MyCat 内存中汇总。若某分片因锁表、慢查询阻塞整个COUNT就卡住。解决方案 A推荐改用SELECT COUNT(*) FROM order WHERE 11 /* shard(all) */强制广播避免单点阻塞方案 B在schema.json中为order表添加mergeSharding: false关闭自动合并改由应用层并发查各分片方案 C业务层改用近似统计如采样SELECT COUNT(*) FROM order TABLESAMPLE SYSTEM (1)。4.2 现象INSERT INTO order VALUES(...)成功但SELECT * FROM order WHERE id1001查不到原因order表未配置autoIncrement:true且插入时未显式指定idMyCat 用0作为默认值导致所有id0的记录被路由到同一分片0 % 2 0→dn1而其他分片无数据。解决立即检查schema.json中该表是否漏配autoIncrement: true若已上线用UPDATE order SET id LAST_INSERT_ID() 1 WHERE id 0修复再重建全局序列起始值预防所有分片表必须显式声明主键生成策略禁止依赖 MySQLAUTO_INCREMENT。4.3 现象SHOW PROCESSLIST在 MyCat 端看到大量Sleep连接netstat显示 ESTABLISHED 连接数飙升原因应用未正确关闭ConnectionMyCat 连接池中的连接被长期占用最终耗尽maxPoolSize新请求排队等待。解决在conf/mycat.properties中开启连接泄漏检测leakDetectionThreshold60000毫秒配合logback-spring.xml开启com.alibaba.druid.pool.DruidDataSource的warn日志定位泄漏代码强制规范所有 JDBC 操作必须用try-with-resources或显式conn.close()。4.4 现象UPDATE order SET amount199.9 WHERE user_id1 AND id1001影响行数为 0原因UPDATE语句中WHERE条件含分片键user_id和非分片键idMyCat 默认只按分片键路由id1001的过滤在分片内执行。若user_id1的数据实际在dn2但该语句被错误路由到dn1则找不到记录。解决在schema.json中为order表添加shardingKeyCheck: true开启分片键强校验或改写 SQLUPDATE order SET amount199.9 WHERE user_id1 AND id1001 /* shard(dn2) */显式指定节点根本解法UPDATE/DELETE必须带分片键且避免混合条件。4.5 现象MyCat 启动后SELECT version返回5.6.29-mycat-2.3.0-release但连接物理 MySQL 显示8.0.33原因MyCat 声称兼容 MySQL 协议但部分高级特性如JSON_EXTRACT,WINDOW FUNCTION未完全实现应用若用了这些语法MyCat 解析失败降级为全节点广播或报错。解决在conf/mycat.properties中设置sqlModeSTRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION关闭 MyCat 的宽松模式使用EXPLAIN命令检查 SQL 是否被下推EXPLAIN SELECT JSON_EXTRACT(data, $.price) FROM order若返回type: broadcast则该 SQL 不支持落地原则MyCat 2.x 仅保证 MySQL 5.7 语法兼容性8.0 新特性需在应用层降级处理。5. 高阶实战用show sql.execute定位慢 SQL 的 3 层穿透法MyCat 最强大的诊断能力藏在它的管理端口9066和命令show sql.execute中。它不像EXPLAIN那样只告诉你“会怎么执行”而是直接展示“刚刚执行过的每条 SQL到底去了哪、干了啥、花了多久”。这是比mycat.log更精准的慢 SQL 定位工具。5.1 连接管理端口并获取实时执行快照# 连接 MyCat 管理端密码默认为 mycat可在 conf/mycat.properties 中改 mysql -h127.0.0.1 -P9066 -umycat -pmycat # 获取最近 100 条执行记录按耗时倒序 show sql.execute limit 100; # 获取特定 SQL 的详细执行链路用 sqlId如 12345 show sql.execute where id12345;返回结果关键字段解读字段含义诊断价值sqlIdMyCat 内部唯一 ID关联日志、追踪全链路sql实际执行的原始 SQL确认是否被重写如SELECT * FROM order可能变成SELECT * FROM order_001executeStatussuccess/fail/timeout判断是否执行失败routeTargetdn1[SELECT * FROM order_001]核心看是否路由到预期节点是否被拆分executeTime毫秒级耗时定位慢点backendTime后端 MySQL 执行耗时若此值高问题在物理库若低而executeTime高问题在 MyCat 网络或解析5.2 三层穿透法从现象到根因的标准化排查流程第一层看routeTarget—— 路由是否正确正常dn1[SELECT * FROM order_001 WHERE user_id1]异常broadcast[SELECT * FROM order WHERE user_id IN (1,2,3)]→ 检查分片算法是否支持IN取模不支持需改范围或加 hint异常dn1[SELECT * FROM order_001], dn2[SELECT * FROM order_002]→JOIN未下推检查 ER 分片配置第二层比executeTime与backendTime—— 瓶颈在哪executeTime1200ms,backendTime1150ms→ 物理库慢查slow_query_logexecuteTime1200ms,backendTime50ms→ MyCat 解析/合并慢检查mycat.log中是否有parse error或merge timeout第三层查sqlId关联日志 —— 深挖上下文在logs/mycat.log中搜索sqlId12345你会看到2024-06-15 10:23:45 [INFO] [ShardingRouter] Route to dn1 with sql: SELECT * FROM order_001 WHERE user_id1 2024-06-15 10:23:45 [DEBUG] [ExecuteHandler] Execute on backend connection: com.mysql.cj.jdbc.ConnectionImplabc123 2024-06-15 10:23:46 [WARN] [MergeHandler] Merge result timeout, cancel all backend tasks→ 第三行MergeHandler超时说明SELECT返回数据量过大如SELECT * FROM order无LIMITMyCat 内存合并超时。解决方案加LIMIT或调大conf/mycat.properties中的mergeTimeout30000。5.3 一个真实案例某支付系统退款查询从 8s 降到 120ms场景SELECT * FROM refund WHERE order_id? AND statusSUCCESS平均耗时 8s。穿透过程show sql.execute发现routeTarget为broadcast且backendTime均 50ms → 问题在广播检查refund表配置发现shardingColumn设为id但查询条件是order_id→分片键与查询条件不匹配修改schema.jsonshardingColumn: order_id并重建分片映射重启 MyCatshow sql.execute显示routeTarget: dn1[SELECT * FROM refund_001 WHERE order_id?]耗时降至 120msbackendTime90msexecuteTime120ms差值为网络传输。我的习惯是每次上线新分片表必用show sql.execute跑 3 条典型 SQL单条件查询、JOIN、聚合截图存档。这比写文档管用——当半年后新人问“为什么这个查询慢”我直接甩出当时的routeTarget截图“你看当时就广播了现在修好了”。希望帮到你。本文还有配套的精品资源点击获取
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →