news 2026/10/9 20:14:06

Mycat 1.6.7.1 分库分表实战:配置、分片规则与避坑指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Mycat 1.6.7.1 分库分表实战:配置、分片规则与避坑指南

简介:本资源为Mycat 1.6.7.1版本的Linux发行包,面向在CentOS7环境下搭建分布式数据库集群的运维与后端开发人员,用于解决大数据场景下的水平扩展、读写分离与负载均衡问题。压缩包共95个文件,约16.74MB,以42个jar依赖库、16个properties配置、10个xml配置及4个sh脚本为主,另含so本地库与wrapper启动组件,覆盖服务运行、分片规则与连接池等核心模块。资源内含server.xml、schema.xml、rule.xml等关键配置及多种分片算法定义文件,可帮助读者理解数据节点划分、哈希与范围分片策略、数据源连接配置及服务启停脚本的使用方式。目前已有494人学习下载,适合需要快速部署Mycat中间件、研究分片与读写分离实现细节的开发者参考。

1. 拿到 Mycat-server-1.6.7.1 这个包,先搞清楚它到底解决什么问题

如果你手上正好有一个Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz,大概率是遇到了这样的场景:后端几套 MySQL 实例,业务代码里散落着一堆分库分表逻辑,改一次路由规则要动好几处代码,运维想加一个只读节点还得让开发配合发版。Mycat 这类数据库中间件的价值就在这——它把自己伪装成一个 MySQL 服务端,应用连它就像连一个普通 MySQL,分库分表、读写分离、路由规则全部下沉到中间件层配置。

这个 1.6.7.1 版本属于 Mycat 1.6 系列里比较成熟的一支,release 时间戳是 2019 年初,基于 JDK 1.7+ 运行,配置以 XML 为主,核心是schema.xml、server.xml、rule.xml三件套。它适合谁?适合那些数据库已经出现单表数据量膨胀、读写压力集中,但又不想大改业务代码的团队。不适合谁?不适合刚起步、单库单表还跑得飞快的项目,中间件本身会带来额外的连接开销和排错复杂度,属于典型的"规模到了才值得上"的东西。

这一篇不讲空泛概念,就顺着这个 tar.gz 包,从解压、配置、启动,一路讲到分片规则怎么设、踩坑怎么排,让你能真正把它跑起来并理解每个参数在干什么。

2. 解压与目录结构:先认清这个包里有什么

2.1 解压命令与目录布局

拿到 tar.gz 第一步永远是先看结构再动手,别急着改配置。用下面命令解压并查看顶层目录:

# 解压到当前目录,会生成 mycat 目录 tar -zxvf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz # 进入目录看结构 cd mycat ls -l

解压后你会看到几个关键目录:bin放启动脚本,conf放全部配置文件,lib放依赖 jar,logs放运行日志。这里有个血泪经验:不要在生产机上直接解压到有中文或空格的路径,Mycat 的启动脚本对路径里的特殊字符处理并不健壮,路径带空格会导致 classpath 拼接出错,启动直接报找不到主类。

2.2 三个核心配置文件的分工

在动手改之前,必须先把三个文件各自的职责分清楚,否则改错文件会浪费大量时间:

配置文件职责改动频率
server.xml定义 Mycat 对外暴露的用户、密码、逻辑库名、端口低
schema.xml定义逻辑库、逻辑表、数据节点、真实物理库连接高
rule.xml定义分片算法和分片字段中

server.xml里最容易被忽略的是<system>标签下的sequnceHandlerType,它决定全局序列号的生成方式,默认是本地文件方式,分布式环境下必须改成数据库方式,否则多节点会生成重复 ID。这个坑后面会细说。

2.3 环境依赖检查

Mycat 1.6.7.1 依赖 JDK,启动前先确认版本:

java -version # 需要 1.7 及以上,推荐 1.8

如果机器上有多个 JDK,务必在bin/mycat脚本里显式指定JAVA_HOME,不要依赖系统默认。我一般会在脚本开头加一行export JAVA_HOME=/your/jdk/path,避免因为环境变量漂移导致启动时好时坏,这种问题排查起来最费劲。

3. 配置一个能跑通的分库分表最小实例

3.1 server.xml:定义逻辑库和访问账号

先配置对外访问入口。打开conf/server.xml,找到<user>标签部分,改成你自己的账号:

<user name="app_user" defaultAccount="true"> <!-- 应用连接 Mycat 时使用的密码 --> <property name="password">app_pass_123</property> <!-- 该账号能访问的逻辑库,对应 schema.xml 里的 schema name --> <property name="schemas">order_db</property> <!-- 是否只读,false 表示可读写 --> <property name="readOnly">false</property> </user>

这里的schemas值order_db必须和后面schema.xml里<schema name="order_db">完全一致,大小写敏感。参数说明:name是登录用户名,password是登录密码,readOnly控制该账号是否只能读。逻辑说明:Mycat 用这套账号体系拦截应用连接,应用端配置的 JDBC 连接串里写的库名就是这里的order_db,而不是真实物理库名。

3.2 schema.xml:把逻辑表映射到真实分片

这是整个配置里最核心的文件。假设我们要把订单表t_order按用户 ID 分成两个库、每个库两张表:

<schema name="order_db" checkSQLschema="false" sqlMaxLimit="100"> <!-- 逻辑表,dataNode 指向下面的分片节点 --> <table name="t_order" dataNode="dn1,dn2" rule="mod-long" /> </schema> <!-- 定义两个数据节点,分别指向不同的物理库 --> <dataNode name="dn1" dataHost="host1" database="order_db_0" /> <dataNode name="dn2" dataHost="host2" database="order_db_1" /> <!-- 物理库连接信息 --> <dataHost name="host1" maxCon="100" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="jdbc:mysql://127.0.0.1:3306/order_db_0" user="root" password="root_pass"> </writeHost> </dataHost> <dataHost name="host2" maxCon="100" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="native" switchType="1"> <heartbeat>select user()</heartbeat> <writeHost host="hostM2" url="jdbc:mysql://127.0.0.1:3307/order_db_1" user="root" password="root_pass"> </writeHost> </dataHost>

关键参数逐个说:sqlMaxLimit="100"是防止应用不带 limit 查询时把全表拉回来,生产环境建议设成 100 到 1000 之间;balance="0"表示不开启读写分离,所有请求走写库,如果配了从库要改成 1 或 2;switchType="1"表示写库宕机自动切换,配合heartbeat心跳检测使用。逻辑说明:应用看到的是order_db.t_order一张表,实际数据被mod-long规则分散到两个物理库的t_order表里,路由对应用完全透明。

3.3 rule.xml:分片算法的选择与参数

mod-long是内置规则,直接引用即可,但你要理解它的分片字段从哪来:

<tableRule name="mod-long"> <rule> <!-- 分片字段,必须是表里真实存在的列 --> <columns>user_id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <!-- 分片数量,必须等于 dataNode 的数量 --> <property name="count">2</property> </function>

这里有个必须记住的约束:count的值必须和table标签里dataNode列出的节点数量一致,写 2 个节点就填 2,填 3 会导致部分数据路由到不存在的节点,插入直接失败。columns指定的user_id必须是查询条件里会带上的字段,否则跨分片查询会退化成全节点扫描,性能反而比单库差。

3.4 启动与连接验证

配置改完,启动服务:

# 启动,-start 表示后台启动 ./bin/mycat start # 查看状态 ./bin/mycat status # 实时看日志,启动失败第一时间看这里 tail -f logs/wrapper.log

启动成功后,用 MySQL 客户端连 Mycat 的默认端口 8066:

mysql -h127.0.0.1 -P8066 -uapp_user -papp_pass_123

连上后执行show databases;应该能看到order_db,再use order_db; show tables;能看到t_order。此时插入一条数据,去两个物理库里分别查,就能验证分片是否生效。如果连不上,先看logs/wrapper.log里的报错,九成是配置文件的 XML 格式错误或端口被占用。

4. 分片规则与全局序列:决定系统能不能长期跑下去

4.1 常用分片算法对比与选型

mod-long只是入门,真实业务里分片字段和算法选错,后期扩容会非常痛苦。常见算法对比如下:

算法适用场景扩容难度数据倾斜风险
mod-long数据量均匀、分片数固定高,扩容需重分布低
范围分片 range按时间或 ID 区间低,追加节点即可中,热点集中
一致性哈希节点频繁增减低低
枚举分片按地区、类型等有限枚举低取决于枚举分布

我一般会这样选:如果业务能接受按时间归档,用范围分片最省心,扩容就是加节点;如果分片字段是用户 ID 且分布均匀,mod-long够用;如果节点数会动态变化,一致性哈希更稳。选型时一定要问自己一句:半年后数据翻倍,我加一个节点要不要停机迁移?这个问题的答案决定了你选哪个算法。

4.2 全局序列号的三种方案

分库分表后,自增主键不再全局唯一,必须用全局序列。Mycat 提供三种方式,在server.xml的<system>里通过sequnceHandlerType切换:

<system> <!-- 0=本地文件 1=数据库 2=时间戳 --> <property name="sequnceHandlerType">1</property> </system>

本地文件方式(0)性能最好但多节点会重复,只适合单节点;数据库方式(1)需要提前在某个库建一张序列表,Mycat 通过数据库锁保证唯一,适合分布式;时间戳方式(2)实现简单但高并发下可能重复。生产环境我基本只用数据库方式,虽然多一次数据库交互,但唯一性有保障。建表语句大致如下:

CREATE TABLE MYCAT_SEQUENCE ( name VARCHAR(50) NOT NULL, current_value INT NOT NULL, increment INT NOT NULL DEFAULT 1, PRIMARY KEY (name) ) ENGINE=InnoDB;

建好后插入一行初始记录,并在schema.xml里配置sequenceHandlerType对应的数据节点,Mycat 启动时会去读这张表。

4.3 ER 分片与父子表绑定

订单和订单明细这类有强关联的表,如果各自按不同字段分片,join 会变成跨库操作,性能极差。Mycat 的 ER 分片通过childTable把子表绑定到父表的分片规则上:

<table name="t_order" dataNode="dn1,dn2" rule="mod-long"> <!-- 子表跟随父表分片,join 时能下推到同一节点 --> <childTable name="t_order_item" joinKey="order_id" parentKey="order_id" /> </table>

joinKey是子表里的外键列,parentKey是父表里的对应列。绑定后,同一个订单的明细一定落在和订单相同的物理节点上,join 就能在单库内完成。这个配置能省掉大量跨库查询,是分片设计里性价比很高的一步。

5. 避坑与排查:那些让新手卡半天的真实问题

5.1 启动报 "Cannot find class" 或端口占用

现象:执行./bin/mycat start后status显示未启动,wrapper.log里报找不到主类或端口被占用。原因通常是JAVA_HOME没配好,或者 8066、9066 端口已被其他进程占用。解决:先在bin/mycat里显式写死JAVA_HOME,再用netstat -tlnp | grep 8066查端口占用,杀掉冲突进程或改server.xml里的端口。

5.2 插入数据报 "can't find datanode"

现象:应用插入时报找不到数据节点。原因多半是rule.xml里count的值和schema.xml里dataNode数量不一致,或者分片字段的值算出来的下标超出了节点范围。解决:核对两处数量是否相等,并确认分片字段没有 null 值——null 值参与取模会得到意外结果。

5.3 跨分片查询返回结果不全

现象:不带分片字段的查询,返回的数据比预期少。原因:Mycat 默认只把查询路由到部分节点,或者sqlMaxLimit截断了结果。解决:确认查询条件是否包含分片字段,如果不包含,要么接受全节点扫描的性能代价,要么在业务层强制带上分片字段。sqlMaxLimit设得太小也会导致结果被截断,按业务实际需要调整。

5.4 主键重复导致插入失败

现象:多节点环境下插入报主键冲突。原因:用了本地文件方式的全局序列,或者根本没配全局序列,各节点各自自增。解决:把sequnceHandlerType改成 1,建好序列表,确保所有节点共用同一个序列源。这个坑在单机测试时不会暴露,一上多节点就翻车,属于典型的"测试环境好好的,生产就出事"。

5.5 连接数暴涨拖垮数据库

现象:Mycat 运行一段时间后物理库连接被打满。原因:dataHost里maxCon设得过大,或者应用端连接池和 Mycat 连接池叠加放大。解决:maxCon按物理库实际承受能力设置,一般单库不超过 100;同时应用端连接池要相应调小,因为应用连的是 Mycat,Mycat 再连物理库,两层连接池会相乘。这个参数关系一定要算清楚,否则数据库会被连接数压垮。

6. 进阶技巧:让 Mycat 在生产环境稳得住

跑通只是第一步,真正让 Mycat 在生产环境长期稳定,靠的是几件不起眼但很关键的事。第一件是慢查询日志的开启与定期分析,在server.xml里把sqlMaxLimit和慢查询阈值配好,定期看logs/mycat.log里执行时间超过阈值的 SQL,这些往往就是没带分片字段的全节点扫描,是性能杀手。第二件是压测验证分片均匀度,上线前用真实数据分布跑一遍,统计每个物理节点的数据量和 QPS,如果某个节点明显偏高,说明分片字段选得不好,趁数据量小赶紧换。

第三件是配置文件的版本管理。schema.xml和rule.xml一旦上线,任何改动都要走版本控制,因为这两个文件直接决定数据路由,改错一个字符就可能导致数据写错库。我习惯在每次改动前先备份,改完用diff对比,确认只动了预期的地方再重启。第四件是灰度扩容的节奏,加节点时不要一次性把流量切过去,先让新节点承接少量分片,观察稳定后再逐步迁移,避免一次性重分布把数据库压垮。

还有一个容易被忽略的点:Mycat 本身不存储数据,它只是路由层,所以它自己的高可用也要考虑。单点 Mycat 挂了整个应用就连不上数据库,常见做法是前面挂一个负载均衡,起两个 Mycat 实例,应用连负载均衡地址。这样即使一个 Mycat 实例出问题,另一个还能顶上。这套组合下来,Mycat 才算真正具备生产可用性,而不是一个"能跑通"的玩具。

我自己踩过最深的一个坑,是早期图省事用了本地文件方式的全局序列,单机测试一切正常,上线加到两个节点后开始零星报主键冲突,排查了大半天才定位到序列号生成方式。从那以后,凡是涉及分布式唯一性的配置,我都会在测试阶段就用多节点环境验证,绝不相信单机测试的结果。希望这些经验能帮你少走一段弯路,帮到你。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 20:12:17

Oracle数据库课程设计实战:从ER图到存储过程与答辩全攻略

简介&#xff1a;一份面向数据库管理与开发学习者的Oracle课程设计配套文档&#xff0c;以“学生考勤系统”为例完整呈现数据库规划、设计、实施与维护流程&#xff0c;适合高校学生完成同类课设时参考。原文档为辽宁工程技术大学课程设计报告&#xff0c;包含背景分析、用户与…

作者头像 李华
网站建设 2026/10/9 20:05:10

Python彩票模拟器:概率统计与保本分析实战

1. 从"中奖幻觉"到概率真相&#xff1a;这个模拟器到底在算什么买彩票这件事&#xff0c;绝大多数人都算过一笔糊涂账。两块钱一注&#xff0c;中了五百万&#xff0c;感觉人生就此翻盘&#xff1b;没中&#xff0c;也就当捐了两块钱做公益。但如果你真的坐下来&…

作者头像 李华
网站建设 2026/10/9 20:02:12

极简三文件HTML模板:语义化结构+可调试静态网页骨架

简介&#xff1a;这是一份面向网页开发初学者的轻量级静态网页模板资源&#xff0c;帮助用户快速理解HTML、CSS与JavaScript协同构建网页的基本流程。资源包含完整的前端三件套&#xff1a;template.html定义页面结构&#xff0c;styles.css负责样式布局&#xff0c;script.js实…

作者头像 李华
网站建设 2026/10/9 19:54:15

Java面向对象核心:继承、super、this与抽象类一次讲透

学Java要是没把继承、super、this、抽象类这几个概念弄明白&#xff0c;后面但凡涉及到类设计、框架源码、设计模式的代码&#xff0c;都会读得很吃力。这不是夸张——我见过太多人循环数组写得飞起&#xff0c;一到继承这里就开始犯迷糊&#xff1a;super能不能不写&#xff1…

作者头像 李华
网站建设 2026/10/9 19:54:06

Claude Code vs Codex 实测:六大任务横评与选型指南

事情要从一周前说起。我把一个积压了很久的 React 项目重构任务交给 Claude Code&#xff0c;它在终端里一口气改了十几个文件&#xff0c;从 class 组件拆成函数组件&#xff0c;还顺手把副作用逻辑收敛进了自定义 hook。任务收工后&#xff0c;我盯着滚动的日志想了很久&…

作者头像 李华
网站建设 2026/10/9 19:49:24

pstack诊断AI编码工具本地卡死:Claude/Codex/Pi Agent进程冲突解析

1. “pstack-claude”不是工具名&#xff0c;而是开发者现场诊断的隐喻切口你搜“pstack-claude”&#xff0c;大概率是在终端里敲下pstack命令后&#xff0c;突然看到进程堆栈里赫然出现claude相关符号——比如libclaude.so、claude_engine、codex_worker&#xff0c;甚至一串…

作者头像 李华