
简介一款基于MyCat 1.6.7.6正式版源码深度定制的按月分表扩展包面向使用MySQL中间件处理海量数据、需要按月自动拆分表结构的开发与运维人员解决了原生版本对subTables动态按月分表支持不足的问题。压缩包共111个文件大小约24.86MB以jar依赖库和properties、xml等配置文件为主同时包含sh管理脚本、sql建表语句、so动态库等辅助内容可覆盖运行、调整、启停与初始化全过程。该扩展包采用BYMONTH模式只需指定起始月份如202101即可通过“tableName_$202101-?”规则自动匹配当前月份配合动态建表机制让子表随日期增长自动扩展避免频繁手工维护分表。已有371人学习下载适合具备MyCat使用经验、正在规划分表方案或准备二次开发的读者参考。 mycat-1.6.7.6_BYMONTH.zip 这个包我最近刚在生产环境完完整整用了一轮。如果你也是第一次接触 Mycat或者正好拿到这个带 BYMONTH 后缀的定制版安装包我建议你先把这篇东西看完。这个文件名里藏着不少信息Mycat 版本是 1.6.7.6BYMONTH 代表编译/定制时集成了按月分片By Month规则一般用于日志表、流水表、订单表这类按时间增长的数据。它能解决的核心问题就是单表数据量过大的时候把数据按照月份拆到不同的物理表/物理库里查询时按时间范围自动路由到对应分区避免全表扫描。我最早用 Mycat 是在三四年前当时公司里一张订单流水表半年就涨到几千万行索引越来越重慢查询一个接一个。后来换了按月分片单表数据量一下子压到几百万行以内查询和归档都轻松很多。如果你也有类似需求这篇文章会讲清楚拿到这个 zip 之后怎么部署、怎么配置 BYMONTH、怎么验证数据真的按月份分出去了以及我在实际落地时踩过的那些坑。1. 先搞明白mycat-1.6.7.6_BYMONTH.zip 到底是什么1.1 从文件名看出版本和用途文件名可以拆成三部分mycat、1.6.7.6、BYMONTH。Mycat 是数据库中间件对外伪装成一个 MySQL 实例应用层不需要改代码照样用 JDBC 连接中间件负责把 SQL 解析、路由到后端的多个 MySQL 节点再把结果合并返回。1.6.7.6 是 Mycat 1.6 系列里比较靠后的版本这个系列的优点是生态成熟、资料多、坑也基本都被踩平了BYMONTH 则是分片规则标记说明这个包内置了“按月分片”的能力或者已经帮你在规则文件里预置了按月切分相关配置。有一点要提醒你网上常见的 Mycat 官方包虽然也支持自定义分片规则但可能要自己配 rule.xml而带 BYMONTH 后缀的包通常是有人做了二次封装把按月分片的算法类直接集成进去了。所以拿到包后第一步不是急着改配置而是先确认里面的 rule.xml、lib 目录下到底有哪些分片算法类避免后面配了半天发现类名对不上。1.2 为什么“按月分片”这么受欢迎时间字段是最天然的分片键。业务数据几乎都带 create_time、order_time、log_time 这类字段按月切分每个物理表只保留一个月的数据数据量可控冷热分明。比如日志表上个月的数据还在被经常查询三个月前的数据基本只做归档这时候把分片对齐到月份做备份、清理、归档都非常顺手。按月分片也很符合 DBA 的日常习惯。常见的归档策略是“保留三个月热数据六个月冷数据”如果你的表本身就是按月分区中间件做路由时只需要根据 SQL 里的时间条件落到对应几个节点而不是把所有分片都查一遍。另一个好处是扩容相对简单下个月要新增节点只要把规则里的结束月份往后扩新数据自动落到新库不需要回填老数据。2. 部署前要准备的东西2.1 环境检查清单先别急着解压建议按下面这个清单过一遍JDKMycat 1.6.x 依赖 Java 8实测用 JDK 1.8.0_202 这类老版本更稳太新的 JDK 偶尔会因为强模块化导致反射报错。MySQL后端数据库建议用 MySQL 5.7 或 8.0需要关闭 ONLY_FULL_GROUP_BY 这种严格模式吗不一定强制但如果 SQL 里 group by 字段和不聚合字段混着查建议提前在 MySQL 的 sql_mode 里去掉这个选项。操作系统CentOS 7.x、Ubuntu 18/20 我都跑过只要有 bash 和 unzip 就行。端口Mycat 默认端口 8066数据端口和 9066管理端口确认没被占用。后端数据节点提前建好物理库和物理表比如 mycat_order_2024_01、mycat_order_2024_02。这里我特别想说不要指望 Mycat 自动建表。Mycat 只做路由不会帮你把分片表在 MySQL 里建出来。你必须在后端每个节点上手动建好对应的物理表否则插入数据时直接报 table doesnt exist。2.2 解压与目录结构拿到 mycat-1.6.7.6_BYMONTH.zip 后放到 /opt 或 /data 这种长期路径下再解压unzip mycat-1.6.7.6_BYMONTH.zip -d /opt/ cd /opt/mycat ls -l正常情况下你会看到这些目录bin启停脚本包括 mycat、mycat.bat 等。conf核心配置目录schema.xml、rule.xml、server.xml、log4j2.xml 都在这。libMycat 运行依赖的 jar 包包括 JDBC 驱动。logs运行日志mycat.log 是主日志wrapper.log 是启动日志。建议你立刻看一下 lib 里有没有 mysql-connector-java 相关的 jar。如果版本太老连接 MySQL 8.0 时会有认证插件问题。我遇到过 lib 里是 5.1.x 的驱动连 MySQL 8.0 报 Public Key Retrieval is not allowed换掉驱动后就好了。2.3 确认安装包是否正常解压后先看版本不要直接启动./bin/mycat version如果能输出版本信息说明环境变量和启动脚本基本没问题。接着看 conf/rule.xml 里有没有 BYMONTH 相关的 function搜一下grep -n -i month conf/rule.xml如果是定制包这里应该能看到类似partbymonth或PartitionByMonth的 function 定义。如果没有别慌后文我会给出完整的配置方法自己加上去也一样。3. 一步步配置 BYMONTH 按月分片3.1 在 schema.xml 里声明逻辑表schema.xml 是 Mycat 的“路由地图”。我们要定义一个逻辑库比如 order_db然后在里面声明一张逻辑表 order_info拆到 4 个后端数据节点。节选一下我的配置schema nameorder_db checkSQLschematrue sqlMaxLimit100 table nameorder_info primaryKeyid dataNodedn_2024_01,dn_2024_02,dn_2024_03,dn_2024_04 rulesharding_by_month / /schema dataNode namedn_2024_01 dataHosthost1 databaseorder_2024_01 / dataNode namedn_2024_02 dataHosthost1 databaseorder_2024_02 / dataNode namedn_2024_03 dataHosthost1 databaseorder_2024_03 / dataNode namedn_2024_04 dataHosthost1 databaseorder_2024_04 / dataHost namehost1 maxCon100 minCon10 balance0 writeType0 dbTypemysql dbDriverjdbc switchType1 heartbeatselect user()/heartbeat writeHost hosthostM1 urljdbc:mysql://192.168.1.10:3306?useSSLfalse usermycat_user passwordyourpass / /dataHost注意这里的规则table 标签的 rule 属性指向 rule.xml 里的 tableRule 名称dataNode 列表顺序要和分片规则算出来的索引对应。比如 BYMONTH 把 1 月路由到第 0 个节点2 月路由到第 1 个节点那就按月份顺序写 dataNode。3.2 在 rule.xml 里定义按月规则rule.xml 里需要两部分tableRule 和 function。tableRule 负责声明“按哪个字段、用哪个算法”function 负责算法实现。如果你拿到的是 BYMONTH 定制包可能已经内置了按月规则但为了保险我一般会自己再核对一遍。下面是一个可用的配置tableRule namesharding_by_month rule columnscreate_time/columns algorithmsharding-by-month/algorithm /rule /tableRule function namesharding-by-month classio.mycat.route.function.PartitionByMonth property namedateFormatyyyy-MM-dd/property property namesBeginDate2024-01-01/property property namesEndDate2025-12-31/property /function这个算法的逻辑是根据 sBeginDate 与当前日期之间的月份差再对节点数取模。比如 sBeginDate 是 2024-01-01传入 2024-03-15月份差是 2如果只有 4 个节点就路由到第 2 个节点也就是 dn_2024_03。如果类名不是PartitionByMonth而是定制包里的MycatPartitionByMonth之类用 grep 查一下 lib 或 conf 里的注释就能看到。不同版本属性名也可能不同有些版本用sBeginDate有些用beginDate我建议你解压后先看 rule.xml 自带的注释再复用。3.3 在 server.xml 里加账号和逻辑库server.xml 里要配置 Mycat 对外暴露的逻辑库名和连接账号。默认文件里会有一个mycat用户密码 123456逻辑库列表为空需要改成你自己的。user nameapp_user property namepasswordapp_pass_2024/property property nameschemasorder_db/property property namereadOnlyfalse/property /user这里 schemas 的值必须和 schema.xml 里 schema 的 name 保持一致否则连上之后看不到库。另外建议不要用默认的 123456 密码生产环境一定要改。如果你还需要从管理端口做配置热加载可以在 server.xml 里加一个只读用户或者直接用命令行工具mysql -uapp_user -papp_pass_2024 -h127.0.0.1 -P9066 -e show database9066 端口是 Mycat 管理端口可以执行 reload config、show datanode 这些指令。4. 启动、连接与数据分布验证4.1 启动 Mycat 并查看日志配置都改完先在前台模式启动一次看实时日志避免后台启动后报错看不到./bin/mycat console如果输出里没有异常再 CtrlC 停掉改用后台方式./bin/mycat start ./bin/mycat status启动过程中最常见的错误是端口被占用、JVM 内存参数设置过大导致启动失败以及 wrapper.conf 里的 java 路径不对。看到WrapperSimpleApp: Encountered an error running main之类的日志多半是 Java 版本或 classpath 问题检查JAVA_HOME和 lib 目录。4.2 用 MySQL 客户端插入数据验证启动成功后用普通 MySQL 客户端连接 8066 端口mysql -uapp_user -papp_pass_2024 -h127.0.0.1 -P8066 order_db先手工插入几条跨月数据INSERT INTO order_info (id, order_no, create_time, amount) VALUES (1, NO20240115, 2024-01-15 10:00:00, 100); INSERT INTO order_info (id, order_no, create_time, amount) VALUES (2, NO20240220, 2024-02-20 10:00:00, 200); INSERT INTO order_info (id, order_no, create_time, amount) VALUES (3, NO20240310, 2024-03-10 10:00:00, 300);然后到后端 MySQL 里分别查order_2024_01、order_2024_02、order_2024_03如果每个表里只有对应月份的数据说明路由正确。4.3 怎么判断数据真的按月分片了光靠应用层 SELECT 看不出来需要走后端库确认。一是直接登录后端 MySQL 节点分别 count 每张物理表的行数二是用 Mycat 管理端口查看路由情况mysql -uapp_user -papp_pass_2024 -h127.0.0.1 -P9066 -e show datanode这能看到每个 dataNode 的连接数、负载等状态。还有一个更直观的验证方式在 Mycat 里执行带时间条件的查询然后在 Mycat 日志里看路由日志。打开 conf/log4j2.xml把io.mycat的日志级别调到 DEBUG执行SELECT * FROM order_info WHERE create_time 2024-02-01 AND create_time 2024-03-01;日志里会出现类似route result的内容能看到这条 SQL 最终路由到了哪个 dataNode。这一步很重要因为有时候你以为走了分片实际是到处扫。5. 实际使用中绕不开的坑5.1 分片键没走索引导致全路由Mycat 路由的基本前提是SQL 的 where 条件里必须带分片键而且最好是等值或范围条件能被中间件解析到。如果你写SELECT * FROM order_info WHERE order_no NO20240220;Mycat 无法根据 create_time 定位到分片只能把这条 SQL 发给所有分片去执行然后合并结果。短时间还行数据量大或者并发高时就是雪崩。解决办法业务 SQL 尽量带时间范围比如 where create_time between ... and ... and order_no ...。如果实在无法避免就要考虑另建一个按 order_no 分片的索引表或者用 Mycat 的 ER 分片、全局表来辅助。5.2 时间类型不匹配导致路由错乱BYMONTH 算法解析日期时对格式很敏感。如果表字段是 datetime传入的是 2024-01-15 10:00:00而 dateFormat 配的是 yyyy-MM-ddMycat 一般也能截断处理但如果你传的是字符串 20240115就可能解析失败路由到默认节点或直接报错。我的建议是表和 SQL 里统一用 datetime 类型dateFormat 统一用 yyyy-MM-ddJava 端传参用Date或LocalDateTime不要拼字符串。遇到解析不了的日期可以在 rule.xml 里给 function 加一个默认节点配置保证解析失败时落到兜底分片而不是整个查询报错。5.3 跨年与月末边界要提前想清楚按月分片最容易出问题的就是跨年。如果 sEndDate 只配到 2024-12-31那么 2025 年 1 月的数据就没有对应分片路由会失败或者落到最后一个节点。所以要么把 sEndDate 配得足够远比如 2025-12-31要么每年提前更新一次 rule.xml 并 reload。另外还要注意每个月天数不一样2 月有平年闰年。Mycat 的月份差算法是拿年份*12月份来算不关心具体天数所以 2024-02-29 和 2024-02-01 会落在同一个分片这是正常的。但如果你用的是按天分片的类似算法就要特别小心月末最后一天的边界值。5.4 全局表要不要做成按月分片有些字典表、用户表不适合按月分片因为它们不分时间。不要把这类表加入到 BYMONTH 规则里否则路由逻辑会变得很别扭。Mycat 里可以在 schema.xml 的 table 标签里不加 rule让它变成单节点表或者用 typeglobal 作为全局表广播到所有数据节点。我踩过一个坑一开始把用户表也配成了按月分片认为“用户创建时间”也能分结果用户数量和订单数量完全不是一个量级旧数据很难迁移后来只能重建逻辑表。所以分片键和分片策略一定要基于真实查询模式来选不要因为“方便”就一刀切。6. 常见问题排查速查表6.1 高频报错与处理方式我把实际使用中遇到最多的问题整理成了表格方便你直接对号入座。错误现象可能原因处理方法启动报WrapperSimpleApp: Encountered an errorJDK 版本不对或 lib 下缺依赖检查 JAVA_HOME确认 JDK 8重新解压完整包连接 8066 被拒绝Mycat 没启动或端口被占用看 logs/mycat.log用netstat -lnp查端口插入数据报table doesnt exist后端物理表未创建到对应的 MySQL 库里手动建表查询结果缺失日期条件没带或者分片键没解析到在 SQL 里补充 create_time 范围并看 DEBUG 日志路由全部落到一个节点rule.xml 的 class 属性错误或 sBeginDate 配置不对确认 function class 路径重新计算月份差MySQL 8.0 连接失败JDBC 驱动版本太老替换 mysql-connector-java 为 5.1.49 以上或 8.x 版本加载配置失败XML 文件格式错误用xmllint校验或者用 IDEA 打开检查标签闭合6.2 一个推荐的排查路径如果数据分布不对不要直接改配置先按这个顺序排查确认 Mycat 日志里这条 SQL 的 route result。确认 rule.xml 的 columns 和 SQL where 条件里的字段名完全一致大小写也一致。确认 sBeginDate 和当前日期之间的月份差计算正确。比如 sBeginDate 是 2024-01-01现在是 2024-05-20月份差是 4如果有 4 个节点实际路由到第 0 个节点因为 4 % 4 0这容易让人误以为没有分片。确认后端 dataNode 顺序和路由索引对齐不要出现 1 月数据路由到 dn_2024_02 这种错位。调完之后热加载配置mysql -uapp_user -papp_pass_2024 -h127.0.0.1 -P9066 -e reload config;然后再插入一条新数据到后端库验证分布。热加载虽然方便但如果是大版本改动我建议还是重启一次 Mycat避免配置缓存导致规则不一致。根据我自己的经验用 mycat-1.6.7.6_BYMONTH.zip 做按月分片最重要的不是把配置文件背下来而是理解“分片键决定了 SQL 的去向”这件事。你只要把时间字段当作路由的唯一线索所有物理表、规则、查询条件都围绕它来设计后面基本不会再出大问题。最后再分享一个小技巧第一次上线前用脚本往后端库灌一批跨月测试数据再用 Mycat 执行各种时间范围查询然后把实际路由节点和预期对照一遍。这个动作看着琐碎但能帮你提前发现 80% 的配置错位问题比上线后回滚舒服多了。本文还有配套的精品资源点击获取