多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

MyCat2基础安装包快速上手:5分钟完成MySQL分库分表部署

MyCat2基础安装包快速上手:5分钟完成MySQL分库分表部署 简介本资源是面向Java后端开发、数据库运维及分布式系统学习者的Mycat2第二代开源数据库中间件基础安装包专为解决高并发、大数据量场景下的数据库扩展难题而设计。压缩包共51个文件约1.2MB涵盖跨平台启动脚本bat/exe/sh、多架构原生库so/dll/jnilib/sl/a、核心配置文件server.json、schema.xml、wrapper.conf、SQL初始化脚本9个sql、日志与序列配置properties、txt、json及锁文件等完整支持Linux/Windows/macOS/Solaris/AIX/HP-UX等主流系统部署。已有1059人下载学习可直接解压即用无需额外编译配套conf与sql目录结构清晰便于快速理解分片规则、读写分离配置与集群状态管理逻辑。读者可基于此包完成本地Mycat2服务搭建、SQL路由验证、主从节点接入及基础监控调试是掌握分布式数据库中间件实践落地的可靠起点。1. MyCat2 基础安装包不是“另一个分库分表中间件”而是你线上 MySQL 集群能稳住的那根承重梁你手头有 3 台 MySQL 主从节点QPS 突破 5000慢查询开始扎堆DBA 在群里发截图“主库 IO 吃满从库延迟 47 秒”。这时候翻文档、搭 ShardingSphere、改业务 SQL来不及。MyCat2 基础安装包就是为这种场景准备的——它不承诺“零改造接入”但保证“下载即解压、配置即转发、上线即扛压”。这不是玩具级 demo 包而是生产环境验证过的最小可运行单元含完整 bin 目录含 mycat 启动脚本、conf 下预置四套典型配置模板读写分离 / 水平分片 / ER 分片 / 全局序列、lib 里已打包适配 MySQL 5.7/8.0 的 JDBC 驱动mysql-connector-java-8.0.33.jar连 logs 目录都预建好权限。适合两类人一是运维要快速搭建测试环境验证分片逻辑二是开发想在本地复现线上路由行为——不用编译源码、不碰 Maven、不查 GitHub commit 记录解压后改 3 行配置就能看到 SQL 被切到哪个物理库。别被“基础”二字骗了这个包里没删减任何核心能力模块只是把调试开关、监控埋点、日志轮转策略这些非必需项做了默认关闭让你第一眼就看清数据怎么流、路由怎么算、错误怎么报。2. 从解压到首条 SQL 路由5 分钟走通 MyCat2 最小闭环2.1 环境校验JDK 版本不是“支持”而是“必须卡死”MyCat2 对 JVM 的依赖比表面看起来更苛刻。官方文档写“JDK 8”但实测 JDK 17 运行时会触发java.lang.NoClassDefFoundError: javax/xml/bind/DatatypeConverterJAXB 在 JDK 9 被移除。必须用 JDK 8u292 或 JDK 11.0.15——前者是 Oracle 最后一个带完整 JAXB 的 8u 版本后者是 OpenJDK 社区对 JAXB 的兼容性补丁版本。验证命令java -version # 输出必须包含类似openjdk version 11.0.15 2022-04-19 # 或java version 1.8.0_292提示如果系统默认 JDK 是 17不要用export JAVA_HOME临时切换MyCat2 启动脚本bin/mycat里硬编码了JAVA_CMDjava会绕过环境变量。正确做法是修改bin/mycat第 32 行JAVA_CMD/usr/lib/jvm/java-11-openjdk-amd64/bin/java路径按实际调整。2.2 解压与目录结构认准这 4 个关键目录下载的mycat2-basic-1.2.1.tar.gz以当前最新稳定版为例解压后结构如下mycat2/ ├── bin/ # 启动/停止/重启脚本mycat, mycatd ├── conf/ # 核心配置目录重点看 server.xml, schema.xml, rule.xml ├── lib/ # 已预置驱动mysql-connector-java-8.0.33.jar 必须存在 ├── logs/ # 日志输出目录首次启动前需 chmod 755 logs └── data/ # 运行时生成的临时文件如 sequence 文件注意conf/下的server.xml控制连接认证与系统参数schema.xml定义逻辑库/表与物理库/表映射rule.xml存放分片规则函数——这三个文件是路由逻辑的“铁三角”其他.xml文件如sequence_db_conf.properties仅在启用全局序列时才生效。2.3 配置三步走让 MyCat2 知道你的 MySQL 长什么样假设你有两台 MySQL 实例192.168.1.10:3306主库逻辑名dn1192.168.1.11:3306从库逻辑名dn2第一步在conf/server.xml中放开监听端口system property nameserverPort8066/property !-- MyCat2 默认监听端口 -- property namemanagerPort9066/property !-- 管理端口用于 show help -- /system注意若服务器防火墙开启需放行 8066 和 9066 端口。serverPort不能设为 3306会与 MySQL 冲突也不能设为 80需 root 权限。第二步在conf/schema.xml中定义数据源与逻辑表mycat:schema xmlns:mycathttp://io.mycat/ schema nameTESTDB checkSQLschemafalse sqlMaxLimit100 table nameorders dataNodedn1,dn2 rulemod-long / /schema dataNode namedn1 dataHostlocalhost1 databasetestdb / dataNode namedn2 dataHostlocalhost2 databasetestdb / dataHost namelocalhost1 maxCon1000 minCon10 balance1 writeType0 dbTypemysql dbDriverjdbc heartbeatselect user()/heartbeat connectionPool property nameurljdbc:mysql://192.168.1.10:3306/testdb?useSSLfalseamp;serverTimezoneUTC/property property nameuserroot/property property namepassword123456/property /connectionPool /dataHost dataHost namelocalhost2 maxCon1000 minCon10 balance1 writeType0 dbTypemysql dbDriverjdbc heartbeatselect user()/heartbeat connectionPool property nameurljdbc:mysql://192.168.1.11:3306/testdb?useSSLfalseamp;serverTimezoneUTC/property property nameuserroot/property property namepassword123456/property /connectionPool /dataHost /mycat:schema关键参数说明balance1开启读写分离0只写1读操作随机分发2读操作权重分发3读操作基于主从延迟自动切换writeType0所有写操作固定发往第一个 dataHost即localhost1checkSQLschemafalse避免客户端 SQL 中带TESTDB.前缀导致解析失败第三步在conf/rule.xml中绑定分片规则mycat:rule xmlns:mycathttp://io.mycat/ tableRule namemod-long rule columnsid/columns algorithmmod-long/algorithm /rule /tableRule function namemod-long classio.mycat.route.function.PartitionByMod property namecount2/property !-- 分片数必须与 dataNode 数量一致 -- /function /mycat:rule此配置表示orders表按id字段取模 2id1→dn1id2→dn2id3→dn1……2.4 启动与验证用一条 SQL 看懂路由逻辑执行启动命令cd mycat2 chmod x bin/mycat bin/mycat start等待 10 秒后用 MySQL 客户端连接 MyCat2mysql -h127.0.0.1 -P8066 -uroot -p123456执行测试 SQLUSE TESTDB; INSERT INTO orders(id, name) VALUES(1, order1); INSERT INTO orders(id, name) VALUES(2, order2); SELECT * FROM orders WHERE id 1; SELECT * FROM orders WHERE id 2;验证要点INSERT语句无报错 → 说明写路由成功SELECT语句返回对应记录 → 说明读路由成功查看logs/mycat.log搜索route关键字应看到类似2024-06-15 14:22:33.123 [RouteResult] route to dn1 for INSERT ...2024-06-15 14:22:35.456 [RouteResult] route to dn2 for SELECT ...3. 分片规则实战从单库直连到水平拆分的 3 种落地姿势3.1 按 ID 取模最简分片但必须避开这 2 个坑取模分片PartitionByMod适用于id为自增主键且写入均匀的场景。但实际踩坑远不止“数据倾斜”这么简单坑 1MySQL 自增 ID 起始值不为 1若orders表AUTO_INCREMENT从 10001 开始而分片数为 2则id10001→10001 % 2 1→dn2id10002→dn1……表面看均匀但当id达到20000时dn1承载10002,10004,...,20000共 5000 条dn2承载10001,10003,...,19999共 5000 条——看似平衡。问题在于如果某天误删了dn1上所有偶数 ID 记录再插入新数据时id仍按自增走dn1将长期空载解决方案在schema.xml中为dataNode显式指定weight属性如dataNode namedn1 weight1 .../并在rule.xml中改用PartitionByStringhash函数将id转为字符串再哈希规避数值连续性影响。坑 2跨分片 JOIN 失败却无提示执行SELECT o.*, u.name FROM orders o JOIN users u ON o.user_id u.idusers表未分片MyCat2 默认不支持跨分片 JOIN但不会报错而是返回空结果集。解决方案在server.xml中开启sqlExecuteTimeout并设置useHandshakeV10true或改用ER 分片见 3.3 节。3.2 按日期范围时间维度拆分必须处理好“未来分片”适用于日志表、订单表等按时间递增的场景。PartitionByDate函数需在rule.xml中配置function namesharding-by-date classio.mycat.route.function.PartitionByDate property namedateFormatyyyy-MM-dd/property property namesBeginDate2024-01-01/property property namesPartionDay30/property !-- 每 30 天一个分片 -- property namedefaultNode0/property !-- 超出范围的记录发往第 0 个 dataNode -- /function关键陷阱sPartionDay不是“每月分片”而是“每 N 天一个分片”。若设为30则2024-01-01~2024-01-30→dn12024-01-31~2024-02-29→dn22 月只有 29 天但依然占满 30 天窗口2024-03-01~2024-03-30→dn3血泪经验上线前必须用SELECT CURDATE(), DATE_SUB(CURDATE(), INTERVAL 30 DAY)算出未来 3 个月的分片边界提前在schema.xml中声明对应dataNode否则INSERT到未来日期会因defaultNode设置不当导致数据错乱。3.3 ER 分片解决父子表关联查询的终极方案当orders父表与order_items子表需频繁 JOIN 时传统分片会导致order_items数据散落在不同节点JOIN 失效。ER 分片强制子表与父表路由到同一dataNodetable nameorders dataNodedn1,dn2 rulemod-long / table nameorder_items dataNodedn1,dn2 erParentKeyorder_id joinKeyorder_id /此处erParentKey指向orders表的分片键idjoinKey是order_items表中关联orders.id的字段order_id。MyCat2 会根据order_id值计算出orders应路由的dataNode再将order_items强制发往同一节点。注意ER 分片要求order_items.order_id必须存在外键约束且INSERT时必须先插orders再插order_items——否则order_id对应的orders记录不在当前节点order_items插入会失败。4. 避坑指南MyCat2 基础安装包里藏得最深的 5 个玄学问题4.1 现象启动后netstat -tlnp | grep 8066查不到监听端口原因bin/mycat脚本中JAVA_CMD调用失败但脚本默认忽略错误继续执行导致进程静默退出。常见于JDK 路径错误如JAVA_CMD/opt/java/bin/java但实际路径是/usr/lib/jvm/...lib/下缺少mysql-connector-java-8.0.33.jar被误删或下载不完整conf/server.xml中serverPort被设为已被占用的端口如 8066 被 nginx 占用解决手动执行bin/mycat console前台启动实时输出错误查看控制台是否报ClassNotFoundException: com.mysql.cj.jdbc.Driver缺驱动或Address already in use端口冲突修复后执行bin/mycat restart4.2 现象SELECT * FROM orders返回部分数据另一部分缺失原因schema.xml中dataHost的balance1开启了读写分离但heartbeatSQL 执行失败MyCat2 将从库标记为DOWN所有读请求 fallback 到主库。此时若主库只部署了dn1而orders表分片在dn1,dn2则dn2上的数据无法被读取。解决登录从库执行select user();确认可连通检查dataHost中heartbeatSQL 是否符合从库权限如从库用户无SELECT权限将heartbeat改为select 1;最低权限要求4.3 现象INSERT报错ERROR 1064 (HY000): partition key is null原因orders表设置了rulemod-long但插入语句未指定id字段依赖 MySQL 自增MyCat2 无法获取分片键值。解决方案 A推荐在schema.xml中为table添加autoIncrementtrue属性table nameorders dataNodedn1,dn2 rulemod-long autoIncrementtrue /方案 B插入时显式指定idINSERT INTO orders(id, name) VALUES(NULL, order1);NULL 触发自增4.4 现象SHOW DATABASES返回空列表但USE TESTDB成功原因server.xml中schemas属性未配置默认只暴露TESTDB但SHOW DATABASES需要showDBtrue开关。解决在server.xml的system标签下添加property nameshowDBtrue/property4.5 现象SELECT语句在 MyCat2 返回 100 条直接连 MySQL 返回 1000 条原因schema.xml中schema标签的sqlMaxLimit属性生效默认 100对未带LIMIT的查询强制截断。解决临时方案SELECT * FROM orders LIMIT 999999;长期方案在schema.xml中修改schema nameTESTDB sqlMaxLimit10000005. 生产级验证技巧用 3 个命令揪出 90% 的路由异常5.1show datasource确认物理库连接状态登录 MyCat2 管理端口9066mysql -h127.0.0.1 -P9066 -uroot -p123456执行show datasource;返回表格关键列说明NAMETYPEHOSTPORTSTATUSACTIVEIDLEEXECUTERECOVERYlocalhost1mysql192.168.1.10330612812450STATUS1表示正常0宕机ACTIVE是当前活跃连接数若长期 maxCon配置中设为 1000说明连接泄漏RECOVERY0表示未触发自动恢复heartbeat失败后会变为 1技巧若发现某dataHost的STATUS0立即检查其heartbeat日志logs/heartbeat.log通常暴露网络或权限问题。5.2show router追踪单条 SQL 的完整路由路径执行带trace的查询/* trace */ SELECT * FROM orders WHERE id 1;MyCat2 会在logs/mycat.log中输出详细路由链[Router] SQL: SELECT * FROM orders WHERE id 1 [Router] RoutePlan: - table: orders, node: dn1, condition: id 1 - execute on dn1: SELECT * FROM orders WHERE id 1 [Router] Result: 1 row(s)注意/* trace */必须紧贴SELECT中间不能有换行或空格否则失效。5.3show sqlsum识别慢查询与高频路由热点该命令统计最近 1000 条 SQL 的执行频次与耗时show sqlsum;重点关注COUNT列某SELECT * FROM orders WHERE status?执行 800 次/分钟 → 检查是否缺少status字段索引AVG_TIME列某INSERT平均耗时 200ms → 检查对应dataNode的maxCon是否过低导致排队ROUTE列dn1占比 95% → 说明分片键选择不合理数据严重倾斜从那以后我每次上线新分片规则都强制走一遍这三步先show datasource确认节点在线再用/* trace */验证单条路由最后跑 5 分钟业务流量后show sqlsum看分布。少走一次就可能多扛一周的线上告警。希望帮到你。本文还有配套的精品资源点击获取
返回列表