首页 / 资讯中心 / 文章详情

MyCat按月分表实战:subTables配置、路由验证与避坑指南

MyCat按月分表实战:subTables配置、路由验证与避坑指南 ★ FEATURED ARTICLE
简介该资源基于 MyCat 1.6.7.6 正式版源码修改面向需要在分库分表场景中实现按月自动分表的后端开发与运维人员重点解决 subTables 正则配置无法按月份动态生成子表的问题。通过 subTablestableName_$202101-?、subTableWayBYMONTH 与 rulesharding-by-month 的组合配置只需指定起始月份问号即代表当前日期月份并动态变化配合 MySQL 中真实存在或动态创建的子表即可实现子表自动增长。压缩包共 111 个文件约 24.86MB以 53 个 jar 依赖、18 个 properties 配置、10 个 xml 与 14 个 txt 说明为主另含 sh 启动脚本、so 本地库及 sql、bak 备份文件覆盖服务端运行与配置所需。已有 379 人学习下载适合研究 MyCat 分表规则改造、需要按月归档或滚动建表的中高级开发者参考可据此理解源码改动点与配置方式快速落地按月分表方案。1. 拿到一个按月分表的 MyCat 包先别急着解压上周有个做订单系统的同行发来一个压缩包名字叫mycat-1.6.7.6_BYMONTH.zip问我能不能直接上生产。他的场景很典型订单表一年几千万行单表查询越来越慢想按月份把数据拆开又不想改太多业务代码。这个包的核心价值就在这儿——它把 MyCat 1.6.7.6 里按月分表subTables 配合 month 规则那套配置和依赖整理成了一个可直接跑的骨架省去你自己拼 schema.xml、rule.xml 的时间。适合谁手里有 MySQL 分库分表需求、想用 MyCat 做中间件、并且数据天然带时间维度的团队。不适合谁数据量还没到单表瓶颈、或者团队没人愿意维护中间件的。下面我按「这东西怎么落地 → 配置怎么写 → 坑在哪」的顺序拆能抄的配置我都贴出来。2. 按月分表的原理与这个包的骨架subTables 到底怎么切2.1 先搞清楚 MyCat 的 month 分片规则在干什么MyCat 的分片规则本质是「路由函数 分片节点映射」。按月分表用的是rule.xml里的sharding-by-month规则它拿分片字段通常是create_time这类日期列去算月份再映射到dataNode。关键在于subTables这个属性它允许一个逻辑表在同一个物理库下再按月份拆成多张物理表比如orders_202401、orders_202402。这跟「分库」是两回事——subTables 是库内分表减少的是单表体积不是单库连接压力。这个包把 1.6.7.6 版本的schema.xml、rule.xml、server.xml模板和启动脚本放在了一起目录大致是conf/、lib/、bin/三块。conf/rule.xml里已经预置了 month 规则的function和tableRule你主要改的是schema.xml里的逻辑表名、分片字段和dataNode列表。理解这一点很重要包给的是「规则骨架」不是「开箱即用的业务配置」业务表名、库名、月份范围都得你自己填。2.2 逻辑表、物理表、dataNode 三者的对应关系假设订单逻辑表叫orders分片字段create_time按月拆到 12 张物理表。配置里要体现三层逻辑表orders业务 SQL 里只写这个名字物理表orders_202401到orders_202412由 subTables 机制拼接dataNode指向具体 MySQL 实例和库比如dn1schema.xml里大致这样写节选字段按你实际表结构调整schema nameORDER_DB checkSQLschemafalse sqlMaxLimit100 !-- 逻辑表 orderssubTables 开启库内按月分表 -- table nameorders dataNodedn1 rulesharding-by-month subTablesorders_$2024$01-12 primaryKeyid/ /schema dataNode namedn1 dataHosthost1 databaseorder_db/subTables的写法是逻辑前缀_$年份$月份范围MyCat 会按规则算出的月份去拼物理表名。这里有个容易翻车的点$2024$01-12这种写法在不同小版本里解析行为不完全一致1.6.7.6 里建议先用单月验证拼接结果再放开全年范围。primaryKey必须写否则后续做全局序列和主键路由会出问题。2.3 为什么选库内分表而不是一上来就分库很多团队一听到分表就想直接分库结果运维复杂度翻倍。按月分表 subTables 的好处是业务代码零改动还是查orders单库内的表体积可控历史月份可以直接归档或删表。代价是单库连接数和磁盘 IO 还是共享的等单库也扛不住了再往分库演进。这个包的定位就是帮你把「库内按月分表」这一步先跑通属于渐进式方案不是终局架构。选型时想清楚你的瓶颈是单表扫描慢还是单库写入打满前者用这个包够用后者得直接上分库。3. 把包跑起来配置、启动与一条 SQL 的完整路由验证3.1 环境准备与目录落位先确认 JDK 版本。MyCat 1.6.x 系列对 JDK 8 兼容最好JDK 11 以上容易在启动时遇到模块反射相关的报错。解压后进目录看一眼结构unzip mycat-1.6.7.6_BYMONTH.zip -d /opt/mycat cd /opt/mycat ls conf/ lib/ bin/ # 确认 rule.xml 里存在 sharding-by-month grep -n sharding-by-month conf/rule.xml如果grep没输出说明包里的规则名可能被改过去rule.xml里搜month关键字确认实际tableRule名后面schema.xml的rule属性要和它严格一致。这一步别跳过规则名对不上启动不报错但查询会全路由到默认节点属于典型的「静默翻车」。3.2 改 schema.xml 和 server.xml 的最小集server.xml主要配逻辑库账号和权限最小改动是加一个能登录的用户user nameapp_user defaultAccounttrue property namepasswordyour_password/property property nameschemasORDER_DB/property /userschema.xml按 2.2 的模板填逻辑表、dataNode、dataHost。dataHost里要写真实 MySQL 的地址、账号、读写节点dataHost namehost1 maxCon100 minCon10 balance0 writeType0 dbTypemysql dbDrivernative switchType1 heartbeatselect user()/heartbeat writeHost hostm1 url127.0.0.1:3306 userroot passwordroot_pwd/ /dataHostbalance0表示不读分离先跑通再说switchType1是默认主从切换策略。参数含义maxCon是连接池上限按月分表场景下物理表多连接消耗会比单表高建议先给到 100 观察。改完配置别急着起服务先做 3.3 的物理表准备。3.3 物理表建表与月份表批量生成MyCat 不会帮你建物理表orders_202401这些得自己在 MySQL 里建好。用一段 SQL 批量生成建表语句避免手写 12 张-- 在 MySQL 里执行生成 2024 年 12 张月表的建表语句 SELECT CONCAT( CREATE TABLE orders_2024, LPAD(n, 2, 0), LIKE orders_template; ) AS ddl FROM ( SELECT 1 AS n UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9 UNION SELECT 10 UNION SELECT 11 UNION SELECT 12 ) t;先建一张orders_template作为结构模板把上面查出来的 DDL 复制执行。逻辑说明LPAD(n,2,0)保证月份是两位和subTables里的$01-12对齐用LIKE复制结构比逐张写字段省事但注意LIKE不带外键和部分索引属性建完抽查一张确认索引在。这一步的坑是月份补零——orders_20241和orders_202401在 MyCat 眼里是两张表拼错就查不到数据。3.4 启动并用 EXPLAIN 验证路由cd /opt/mycat/bin ./mycat start tail -f ../logs/mycat.log # 另开窗口连上逻辑库 mysql -h127.0.0.1 -P8066 -uapp_user -p ORDER_DB连上后执行一条带分片字段的查询并用EXPLAIN看路由EXPLAIN SELECT * FROM orders WHERE create_time 2024-03-15 10:00:00;正常应该只路由到dn1且物理表是orders_202403。如果EXPLAIN显示路由到所有节点八成是rule属性名和rule.xml里的tableRule不一致或者分片字段类型和规则里的columns对不上。验证通过后再跑一条不带分片字段的查询观察是否全路由——这是预期行为业务上要尽量避免。4. 避坑清单按月分表最容易翻车的五个地方4.1 现象查询报「table doesnt exist」但物理表明明建了原因subTables拼接出的表名和你实际建的表名不一致最常见是月份没补零或者$年份$月份范围的写法里年份位数不对。解决在 MySQL 里SHOW TABLES LIKE orders_%对照再用EXPLAIN看 MyCat 实际拼的表名两边对齐。我一般会先只配一个月$2024$03验证拼接通了再放开全年。4.2 现象插入数据成功但查不到原因插入时create_time传了NULL或格式不是yyyy-MM-dd HH:mm:ssmonth 规则算不出月份数据被路由到默认节点或报错丢弃。解决分片字段在业务层强制非空并在 MyCat 侧确认rule.xml里 month 规则的dateFormat和你的入参格式一致。这个坑很隐蔽因为插入不报错。4.3 现象跨月查询把 12 张表全扫一遍慢得离谱原因SQL 的WHERE里没有分片字段或者用了create_time的函数包裹如DATE_FORMAT(create_time,...)规则无法下推。解决查询条件直接写create_time BETWEEN 2024-03-01 AND 2024-03-31别在字段上套函数报表类跨月查询走单独的汇总表别指望 MyCat 帮你优化全路由。4.4 现象启动正常但连接一会儿就断原因dataHost的maxCon给太小月表多、并发一上来连接池打满或者 MySQL 侧wait_timeout比 MyCat 心跳间隔短。解决maxCon按并发估先 100 起步heartbeat保持默认select user()并确认 MySQL 的wait_timeout大于心跳周期。日志里搜connection关键字能快速定位。4.5 现象历史月份数据想归档直接 DROP 表后 MyCat 报错原因subTables范围里还包含被删的月份路由到不存在的表。解决归档前先改schema.xml缩小subTables范围并 reload再删物理表或者保留空表结构只清数据。顺序反了就得回滚配置血泪经验是「先改配置后动数据」。5. 进阶用全局序列和按月归档把方案跑成闭环跑通基本路由只是第一步真正上生产还得解决主键和归档两件事。按月分表后自增主键在每张月表里独立跨表会重复必须换全局序列。MyCat 支持本地文件、数据库、ZK 等方式小规模用数据库方式最省事在某个库建MYCAT_SEQUENCE表schema.xml的table上加autoIncrementtrue并配sequenceHandlerType。我一般会在server.xml里把sequnceHandlerType设为 2数据库方式然后建表CREATE TABLE MYCAT_SEQUENCE ( name VARCHAR(50) NOT NULL, current_value BIGINT(20) NOT NULL, increment INT NOT NULL DEFAULT 1, PRIMARY KEY (name) ) ENGINEInnoDB; INSERT INTO MYCAT_SEQUENCE(name, current_value, increment) VALUES (orders, 100000, 1);逻辑说明current_value是当前已分配到的值increment是步长MyCat 每次取一批缓存在本地减少数据库往返。参数上步长别设太大否则重启后 ID 跳变明显也别设 1高并发下会频繁打库。配完重启插入一条不带id的记录看是否自动填上全局 ID。归档这块我的习惯是每月初跑一个脚本先把上上个月的表数据INSERT INTO orders_archive_YYYYMM SELECT * FROM orders_YYYYMM确认行数一致后再TRUNCATE原月表最后改schema.xml的subTables范围并 reload。顺序不能乱先归档再缩范围再清表任何一步失败都能回退。验证方法很简单归档后跑一条跨归档月的查询确认 MyCat 不再路由到已清空的表同时业务侧读历史数据走归档表。从那以后我每次拿到这种「预置规则」的中间件包都强制先只配一个月、跑通一条EXPLAIN再放开全年范围——这个习惯帮我躲过了至少三次静默路由错误。希望帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?
咨询建站