简介:这是面向 CentOS7 等 Linux 环境的 Mycat 1.6.7.1 分布式数据库中间件完整安装包,适合需要实现 MySQL 水平扩展、分库分表、读写分离或解决单库性能瓶颈的运维与开发人员。压缩包共 95 个文件,整体大小约 16.74MB,核心由 42 个 jar 依赖库组成,覆盖 Mycat 主程序及 Netty、Druid 连接池、Fastjson 等常用组件;16 个 properties 与 10 个 xml 分别承担动态属性及数据源、分片规则等结构化配置;4 个 sh 脚本用于启停、初始化和数据迁移;另附 3 个 so 动态库以兼容不同 Linux 架构。包内自带数据源、分片规则等核心配置模板,并附哈希、范围、枚举分片规则示例,便于快速部署与二次修改。目前已有 494 人学习下载。通过解压并调整分片规则、连接池与 JVM 参数,可快速搭建高可用的数据库中间层,支撑大规模并发与海量数据场景,同时为理解 Mycat 的目录结构、路由机制和运行原理提供完整参照。
1. 还在用 Mycat 1.6.7.1:稳定 release 的最后一班车
Mycat 这个版本号在中间件圈子里算是个分水岭:1.6.7.1 是 1.6 系列里最后一批带日期后缀的稳定 release,发布几年后仍然有不少生产环境跑在它上面。原因很简单——新版本虽然有更好的协议支持和性能优化,但 1.6.7.1 的解压即用、配置直观、踩坑记录全网可查,这三个特性对一线运维来说比任何新特性都值钱。这套 Linux 版的 tar 包,解决的是 CentOS 7 上从零搭起一套分库分表中间件的问题:单库扛不住读压力、分表逻辑散落在业务代码里没法收口、需要读写分离但不想改业务连接方式。适合正在做数据库拆分或打算引入数据库中间件的后端开发和 DBA,花半小时解压配置,比重新造一套数据访问层轮子快得多。
2. CentOS 7 上的部署准备:JDK、目录规划和第一个启动脚本
2.1 先确认三件事:JDK 版本、解压目录、权限
Mycat 是纯 Java 写的数据中间件,对 JDK 版本敏感,这一步翻车最多。常见做法是装 1.8,注意要的是 Oracle JDK 或 OpenJDK 都行,但版本号必须大于 1.8.0_112。比较新的 JDK 版本(比如 11、17)跑 1.6.7.1 大概率会在启动阶段抛 UnsupportedClassVersionError 或者线程池初始化异常,不是不可以跑,而是需要额外改 wrapper.conf 里的 classpath,投入产出不划算。
目录规划上,一般放在/usr/local/mycat或/opt/mycat。我倾向/usr/local/mycat,理由是后续做 systemd 托管和日志按天切割时路径短、手敲命令方便。解压后整个目录在 60MB 左右,全是文本配置和 jar 包,不需要额外装依赖。注意一下/usr/local下要有写权限,正式环境建议单独建 mycat 用户跑服务,别用 root 直接启动——中间件进程如果被提权利用,root 跑就是灾难。
CentOS 7 上还需确认一个隐藏依赖:libaio和numactl。虽然 Mycat 本身是 Java 应用不直接调 aio,但部分环境的 JVM 在启动时会尝试加载这些系统库,缺了以后日志里会报Native memory allocation (mmap) failed。装一下不亏:
yum install -y libaio numactl java -versionJDK 输出正常后,切到安装目录做解压和目录收编。命令按顺序执行:
cd /usr/local tar -xzf Mycat-server-1.6.7.1-release-20190213150257-linux.tar.gz mv mycat mycat-1.6.7.1 ln -s /usr/local/mycat-1.6.7.1 /usr/local/mycat chown -R mycat:mycat /usr/local/mycat-1.6.7.1解压后强制把目录名改成带版本号的形式,再软链到固定路径,这个习惯后面会救你一次——以后同时维护两个版本做灰度切换,只需要把软链换成旧版本目录,连接串一行不用动。chown那一步是给后面独立用户启动做铺垫,如果当前环境只有一个测试机,先跳过也不算错。
2.2 wrapper.conf 的参数边界:内存给多少、目录指向哪
conf/wrapper.conf是本版本最容易被忽略的启动入口。它控制 JVM 的堆内存、启动超时和日志行为。默认参数里wrapper.java.initmemory和wrapper.java.maxmemory分别是 1024M 和 2048M,在 4G 内存的小机器上跑大分片会有压力,需要调整。还有两个参数很关键:wrapper.working.dir决定进程的工作目录,默认是../,相对路径在 systemd 场景下会解析错;wrapper.logfile决定 wrapper 日志路径,默认只保留 3 个滚动文件,做日志归档时要提前改大。
我一般会这样改:
vim /usr/local/mycat/conf/wrapper.conf重点看这几行:
wrapper.java.initmemory=1024 wrapper.java.maxmemory=2048 wrapper.working.dir=/usr/local/mycat wrapper.logfile=/var/log/mycat/wrapper.log wrapper.logfile.rollmode=SIZE wrapper.logfile.maxsize=100m wrapper.logfile.maxfiles=5initmemory和maxmemory设为 1024/2048 是保守值,单机分片数不超过 8 个、每片数据量在百万级以内够用。working.dir改成绝对路径解决的是 cron 或 systemd 环境下当前目录不确定的问题。wrapper.logfile路径要提前建好,否则 wrapper 进程启动时会因找不到目录直接退出。这里顺带提一个容易忽略的点:wrapper.conf 里的wrapper.java.additional.1默认带了一串-Dfile.encoding=UTF-8,千万别删——Mycat 对中文表名和注释的解析依赖这个参数。
2.3 启动失败的快速归因:看 wrapper.log 而不是 mycat.log
第一次启动大概率会翻一次车,这不丢人。关键是知道去哪看原因。Mycat 有两层日志:wrapper.log 记 JVM 启动生命周期,mycat.log 记 SQL 路由、连接池和数据节点状态。启动失败时先看 wrapper.log,常见错误无非是:端口被占用(8066/9066)、JVM 参数不合法、系统库缺失。这些在 wrapper.log 前三行就能定位。mycat.log 里看不到 JVM 启动错误,因为那时代码还没跑到初始化阶段。
/usr/local/mycat/bin/mycat start sleep 2 tail -30 /var/log/mycat/wrapper.logmycat start是后台启动,进程拉起后立刻退出终端。如果 wrapper.log 里出现Startup failed字样的同时 mycat.log 也没有新写入,基本可以断定是端口被占或者 wrapper 配置错误。这时候先去查端口:
netstat -lntp | grep -E "8066|9066"8066 是数据端口,业务连接 Mycat 走它;9066 是管理端口,DBA 执行show @@database这类管理命令走它。两个端口都监听才算启动成功。只起来一个端口的情况我遇过一次——server.xml 里 user 标签的 readOnly 配错导致管理端口拒绝认证,服务端口却正常,排查时容易误判成端口冲突。
3. 三个核心配置文件:schema.xml、server.xml、rule.xml 的协同逻辑
3.1 server.xml:逻辑库用户、端口和 SQL 解析规则
server.xml 管的是 Mycat 对外暴露的身份:用户、密码、可访问的逻辑库、默认端口。注意这里的用户名密码是 Mycat 自己的账号体系,和底层 MySQL 账号完全独立。业务侧连进来的用户叫mycat,密码123456,它被限制只能访问名为litemall的逻辑库。这个逻辑库名在 schema.xml 里也有定义,两文件必须保持一致,否则启动直接报Invalid schema name。
<mycat:server xmlns:mycat="http://io.mycat/"> <system> <property name="defaultSqlParser">druidparser</property> <property name="charset">utf8mb4</property> <property name="frontSocketSoRcvBuf">1048576</property> <property name="frontSocketSoSndBuf">1048576</property> </system> <user name="mycat" defaultAccount="true"> <property name="password">123456</property> <property name="schemas">litemall</property> <property name="readOnly">false</property> </user> <user name="mycat_manager"> <property name="password">654321</property> <property name="schemas">litemall</property> <property name="readOnly">true</property> </user> </mycat:server>charset设utf8mb4是必须的,否则 emoji 字符写入时会被 MySQL 端截断甚至报 Incorrect string value。frontSocketSoRcvBuf和frontSocketSoSndBuf是前端 socket 缓冲区,默认是 1024KB,高并发下如果出现Packet too big这种异常,优先加大这两个值。druidparser是 SQL 解析器,1.6.7.1 默认用它,对复杂 join 和子查询的容错比旧版 parser 好很多。建议业务 SQL 里有超过三张表 join 的场景都保持这个配置别动。
第二个用户mycat_manager是只读账号,专门给报表查询和运营后台用。逻辑库还是同一个,但readOnly为 true 后,DML 语句会被 Mycat 直接拒绝。这种做法在生产里很有用:运营误操作导致的全表 update 会因为只读约束被挡在中间件层,而不是到达底层数据库。
3.2 schema.xml:逻辑库、数据节点和读写分离的映射关系
schema.xml 是 Mycat 里最核心也是配置量最大的文件。它定义三件事:逻辑库里有哪些表、这些表的数据落在哪些物理库、物理库的主从结构怎么组织。先看一个基础配置,然后逐个拆解参数。
<mycat:schema xmlns:mycat="http://io.mycat/"> <schema name="litemall" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"> <table name="orders" dataNode="dn1,dn2" rule="mod-long" /> <table name="product" dataNode="dn1,dn2,dn3" rule="sharding-by-intfile" primaryKey="id" type="global" /> <table name="region" dataNode="dn1" /> </schema> <dataNode name="dn1" dataHost="localhost1" database="litemall_1" /> <dataNode name="dn2" dataHost="localhost1" database="litemall_2" /> <dataNode name="dn3" dataHost="localhost1" database="litemall_3" /> <dataHost name="localhost1" maxCon="1000" minCon="10" balance="1" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"> <heartbeat>select user()</heartbeat> <writeHost host="hostM1" url="jdbc:mysql://192.168.1.10:3306" user="root" password="123456"> <readHost host="hostS1" url="jdbc:mysql://192.168.1.11:3306" user="root" password="123456" weight="1" /> <readHost host="hostS2" url="jdbc:mysql://192.168.1.12:3306" user="root" password="123456" weight="2" /> </writeHost> </dataHost> </mycat:schema>orders表落在 dn1 和 dn2 两个数据节点,分片规则是mod-long,也就是对 id 取模。product落在三个节点,按sharding-by-intfile枚举分片。region不配置 rule,数据只落在 dn1,这是全局表之外的另一种做法:小表不分片。type="global"是全局表定义,product 表在三个节点各存一份全量数据,适合商品维表这种读多写少的表。写入时 Mycat 会广播到所有节点,查询时只路由到其中一个节点,避免跨节点 join。
dataHost标签里的balance="1"是读写分离策略中最常用的:读请求在 writeHost 和 readHost 之间按权重随机分发,写请求永远走 writeHost。writeType="0"表示只在配置的第一个 writeHost 上执行写操作,switchType="1"表示主库宕机时自动切换读写分离状态。heartbeat用select user()是最轻量的探活 SQL,每 3 秒执行一次,别改成select 1之外的复杂语句。
关于checkSQLschema有个细节:设为 false 时,业务 SQL 里写litemall.orders这种带库名的语句,Mycat 会尝试把库名剥离后再路由。如果业务代码里到处是这种写法,建议保持 false;但如果 SQL 里有跨库 join 的意图,这个参数会让路由判断出错——跨库 join 在分片中间件里本来就不支持,遇到这种 SQL 直接改业务逻辑,别指望中间件替你兜底。
3.3 rule.xml:四种分片规则的选择标准和边界条件
rule.xml 定义分片字段、分片算法和算法参数。1.6.7.1 自带几十种算法,生产上用到的其实就那几种。table 标签里的rule="mod-long"指向的就是 rule.xml 中 id 为mod-long的 rule 节点。
<tableRule name="mod-long"> <rule> <columns>id</columns> <algorithm>mod-long</algorithm> </rule> </tableRule> <function name="mod-long" class="io.mycat.route.function.PartitionByMod"> <property name="count">2</property> </function> <tableRule name="sharding-by-intfile"> <rule> <columns>region_id</columns> <algorithm>hash-int</algorithm> </rule> </tableRule> <function name="hash-int" class="io.mycat.route.function.PartitionByFileMap"> <property name="mapFile">partition-hash-int.txt</property> <property name="type">0</property> <property name="defaultNode">0</property> </function>mod-long的count必须和该表实际使用的 dataNode 个数一致。orders用了 dn1、dn2 两个节点,count 就是 2。如果 count 配成 3 而只有两个节点,id 对 3 取模分散到 3 个区域,路由到 dn3 时直接报找不到表。sharding-by-intfile读的是partition-hash-int.txt里的枚举映射,文件内容形如10000=0,含义是 region_id 为 10000 的数据落到第 0 个数据节点。type="0"表示分区字段是 int 类型,如果分区字段是字符串,要改成 1。defaultNode是兜底节点,枚举里没覆盖到的值全丢到这,配错会导致数据倾斜。
选分片规则就一条准则:优先用枚举分片,其次取模,最后才考虑范围分片。枚举分片的边界最可控,扩容时只需要改 mapFile 增加映射即可,数据不用大面积迁移。范围分片适合时间字段做归档场景,比如按月份分片,缺点是热点永远在最新节点上,老节点又闲置。取模分片适合 id 均匀增长且不需要按时间查询的场景。
4. 启动、验证和初步排查:从日志到管理端口的全流程
4.1 启动方式对比:console 模式 vs start 模式
Mycat 启动有两种方式:console和start。调试阶段用 console,日志实时打到终端,Ctrl+C 直接停机;正式运维用 start,进程 daemon 化,日志写文件。很多人第一次调配置时用 start 模式,启动失败后日志不清不楚,白白浪费时间。我的习惯是先 console 跑一次,确认无报错后再换 start。
/usr/local/mycat/bin/mycat console启动成功的标志是日志输出Server startup successfully,同时看到reportSupport之类的例行打印。如果一直卡在connect to datasource那一步,说明 schema.xml 里 dataHost 的地址端口配错,或者某个物理库账号密码不对。此时 console 模式会直接显示超时堆栈,定位比翻文件快太多。
确认 console 模式正常后,切回正式启动并做一次健康检查:
/usr/local/mycat/bin/mycat start sleep 5 jps -l | grep Mycat netstat -lntp | grep -E "8066|9066"jps能看到进程全名,确认是 Mycat 而非其他 Java 进程,避免端口占用排查时找错对象。netstat确认 8066 和 9066 都在 LISTEN,这个双端口都存活的标准在 1.6.7.1 里尤其重要——某些异常情况下进程没死但端口只起了一个,直接ps -ef会误判正常。
4.2 用 mysql 客户端验证路由和分片结果
Mycat 对业务侧伪装成 MySQL 服务器,所以直接拿 mysql 客户端连 8066 就能做 SQL 验证。这里有个注意点:连接 Mycat 时-h指向的是 Mycat 所在机器,不是物理库 IP;-P是 8066 数据端口。物理库的连接信息已经在 schema.xml 里配好了,业务侧感知不到。
mysql -umycat -p123456 -h127.0.0.1 -P8066 litemall进去后先看逻辑库和表:
SHOW DATABASES; SHOW TABLES; EXPLAIN SELECT * FROM orders WHERE id = 1001;EXPLAIN在 Mycat 里不是真解释执行,而是打印这条 SQL 的路由结果,能看到它被分发到哪个 dataNode、命中了哪个分片。这是验证分片规则对不对最直接的方式,没有之一。如果EXPLAIN显示dataNode: dn1,说明 id=1001 这条数据应该在 dn1 上。再去对应物理库手动查一次:
SELECT * FROM litemall_1.orders WHERE id = 1001;两边能对应上,分片配置就是通的;对不上,就是 rule.xml 的算法参数和物理库里的实际数据不一致,通常发生在已存数据后改分片规则。补一条:这种验证不能在现网做,物理库里得先有按分片规则预先拆好的数据,不然单库里有记录、分片路由却落到别的节点,怎么查都是空的。
4.3 常见日志快速定位表:wrapper.log 和 mycat.log 的分工
日志排查是 Mycat 日常运维的重要内容。1.6.7.1 有两层日志,分工明确。wrapper.log 只在 JVM 启动参数错误、端口占用、JVM crash 时才有输出。mycat.log 记录 SQL 路由、连接池状态、主从切换事件和数据节点健康检查。遇到问题先问一句:是进程没起来还是 SQL 有问题?进程没起来看前者,SQL 有问题看后者。
| 日志文件 | 典型内容 | 排查场景 |
|---|---|---|
| wrapper.log | JVM 参数、启动异常、OOM dump | 启动失败、端口占用、进程崩溃 |
| mycat.log | SQL 路由结果、连接池超时、heartbeat 失败 | SQL 慢、数据查不到、主从切换 |
mycat.log 里的时间戳默认是本地时间,但 1.6.7.1 的日志框架配置里有个坑:滚动文件命名用的是 UTC 时间,按天切割时文件名时间和日志里打印的时间会差 8 小时。排查问题按时间范围 grep 时容易被误导。解决办法是改conf/log4j2.xml里RollingRandomAccessFile的 timezone 参数,加一个本地时区。这个不动也不影响功能,但归档日志追溯时确实会让人挠头。
5. 避坑记录:CentOS 7 + MySQL 5.7/8.0 下的七个翻车点
5.1 物理库连不上:heartbeat 报错但启动不报错
现象:Mycat 启动成功,8066 端口正常监听,但业务查询时所有 SQL 都报Connection refused或No datasource。看 mycat.log 里只有 heartbeat 探活的报错循环。
原因:schema.xml 里 dataHost 的 url 配置用的是127.0.0.1,但物理库并不在本机。Mycat 启动时不会强制校验物理库连通性,只要配置格式合法就正常对外服务,直到真实 SQL 路由过去才发现连不上。heartbeat 的select user()每 3 秒失败一次,日志被刷屏但进程不挂。
解决:把url="jdbc:mysql://127.0.0.1:3306"改为实际物理库 IP;顺带检查物理库的 bind-address 是否允许远程连接。另外确认物理库的 max_connections 够用,Mycat 的 dataHost 里maxCon="1000"是逻辑连接数上限,如果物理库实际只有 100 个连接配额,Mycat 会把底层连接池打爆。
5.2 JDK 版本引发的延迟抛错
现象:Mycat 能启动,但跑一段时间后随机出现OutOfMemoryError或GC overhead limit exceeded,重启后恢复正常,过几小时又复发。
原因:JDK 是 1.8.0_40 这类偏老的小版本,JVM 里默认的 G1 垃圾回收器在 1.6.7.1 的大分片对象分配场景下频繁触发 full GC。1.6.7.1 发布时测试环境大多用 1.8.0_112 之后的版本,老版本 JDK 的 G1 在内存碎片化后会出现这个特征。
解决:升级 JDK 到 1.8.0_222 及以上,或者在 wrapper.conf 里显式指定 CMS 回收器:
wrapper.java.additional.10=-XX:+UseConcMarkSweepGC wrapper.java.additional.11=-XX:CMSInitiatingOccupancyFraction=70CMSInitiatingOccupancyFraction=70是让 CMS 在老年代用到 70% 时提前触发回收,这个参数能有效降低 1.6.7.1 在高并发下的 GC 停顿。注意升级 JDK 后要重新确认JAVA_HOME环境变量指向新版本,很多系统装了新版 JDK 但 shell 里还是老路径。
5.3 MySQL 8.0 认证插件导致的连接反复中断
现象:物理库是 MySQL 8.0,Mycat 启动正常,但 SQL 执行时时报Communications link failure,有时连续成功几次后突然断一次。
原因:MySQL 8.0 默认认证插件是caching_sha2_password,而 Mycat 1.6.7.1 的 jdbc 驱动是 5.1.x,只支持mysql_native_password。每次 Mycat 去拿连接时,8.0 服务端要求用新的认证方式,5.1 驱动协商失败后偶尔能蒙对一两次,但大多数情况下直接断开。
解决:在 MySQL 8.0 服务端把 Mycat 连接用的账号改回老插件:
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY '123456'; FLUSH PRIVILEGES;如果不想动 root 账号,新建一个专用账号更干净。另外 MySQL 8.0 的wait_timeout默认 8 小时,Mycat 的空闲连接池连接在这个时间后会被服务端回收,下次请求时拿的是一根死连接。解决办法是把 dataHost 的connTimeout参数调小,低于物理库的 wait_timeout,让 Mycat 主动丢弃死连接。
5.4 全局序列号并发重复:文件方式在高并发下会翻车
现象:业务将 orders 表的 id 交给 Mycat 全局序列号生成,压测时出现主键冲突,且冲突比例随并发升高。
原因:1.6.7.1 默认的全局序列号实现是本地文件方式,序列号值存在sequence_conf.properties里。每次生成先读文件再加一写回,分布式环境下多个 Mycat 实例同时操作同一份文件时没有任何锁机制,重复在所难免。
解决:改用数据库方式生成全局序列号。这个方式需要在一张物理库表里维护当前序列号,Mycat 每次从表里取一段号缓存到内存中。配置步骤分为三步:
# 1. 在物理库执行建表脚本 CREATE TABLE mycat_sequence ( name VARCHAR(50) NOT NULL, current_value INT NOT NULL, increment INT NOT NULL DEFAULT 100, PRIMARY KEY (name) ) ENGINE=InnoDB;# 2. 插入一条序列记录 INSERT INTO mycat_sequence (name, current_value, increment) VALUES ('orders_id', 0, 100);# 3. 修改 conf/sequence_db_conf.properties,配置物理库连接指向 # 格式:序列名=物理库地址:端口:数据节点 orders_id=192.168.1.10:3306:dn1改完重启 Mycat。increment=100表示每次从库里取 100 个号缓存到内存,用完再取。这个值一般不用改,100 足够支撑普通业务峰值;取太大重启时会丢失较多未使用的号,取太小则每次取号都要查库,消耗性能。
5.5 CentOS 7 防火墙拦截:端口明明监听了却连不上
现象:netstat显示 8066/9066 都在监听,本机 mysql 客户端连接正常,但其他机器连不上,报Can't connect to MySQL server on 'xxx'。
原因:CentOS 7 默认启用 firewalld,8080 之外的端口默认不放行。很多教程只讲防火墙要关,没讲清楚到底关的是什么——systemctl stop firewalld只是临时关闭,重启后自动拉起,等于没关。
解决:按需开放两个端口,保留防火墙对其他服务的保护能力:
firewall-cmd --zone=public --add-port=8066/tcp --permanent firewall-cmd --zone=public --add-port=9066/tcp --permanent firewall-cmd --reload--permanent是持久化规则,reload 后立即生效。这个操作之后,用另一台机器跑一遍telnet 本机IP 8066,通了才算完事。顺带确认一下业务连接的机器和 Mycat 机器之间没有安全组拦截,云服务器上 Linux 防火墙放行了但控制台安全组没放行的案例也不少。
5.6 balance 参数理解偏差:读写分离没生效
现象:把 dataHost 的balance配成1,但读 SQL 全部打到主库,从库的监控上看不到任何读流量。
原因:balance="1"的语义是“从库参与读流量的负载均衡”,但不是所有读 SQL 都会被分发到从库。balance为 1 时只有不在事务内的读语句才可能走从库,事务内的读仍然走主库。很多业务框架(比如开了事务的 Spring 服务)每个查询都在事务里,读流量自然全在主库。
解决:确认业务侧有没有隐式事务。如果有事务包裹,要么把查询从事务里摘出来,要么接受事务内读主库的设计——后者在很多一致性要求高的场景里反而是对的。另外balance="2"是“所有读都走从库”,听起来更彻底,但主从延迟超过几秒时,业务会读到旧数据,只能用在容忍最终一致性的报表场景。
5.7 改配置不重启导致的“改了没生效”假象
现象:修改了 server.xml 里的用户密码,用新密码连接还是报错;改了 rule.xml 的分片规则,查询结果没有任何变化。
原因:Mycat 启动时把配置文件加载到内存,运行时不再读盘。配置文件的热加载只覆盖部分参数,而且需要手动触发reload @@config管理命令。如果没有执行 reload,改的配置全在下一班重启后才生效。
解决:执行管理命令重新加载配置,不需要重启进程:
mysql -umycat -p123456 -h127.0.0.1 -P9066 mysql> reload @@config;这个命令执行后,schema.xml 和 rule.xml 都会被重新解析。server.xml 里的用户信息用reload @@userstat单独加载。如果 reload 后报语法错误,说明新配置格式有问题,此时 Mycat 会保留内存中的旧配置继续运行,系统不会挂掉——这点设计比直接重启安全得多。
6. 把读写分离和监控养成一套固定动作:每天一次 show @@datasource
负载调整到稳定后,真正的长期维护工作只剩两件:确认读流量按预期分摊,以及关注主从切换状态。这两件事用一条管理命令就能完成,关键是要养成固定巡检的习惯。
mysql -umycat -p123456 -h127.0.0.1 -P9066 mysql> show @@datasource;输出结果里的RUNTIME列如果持续增长,说明有连接泄漏,排查方向是业务连接池是否设置最大空闲时间;ACTIVE列占比超过 80% 时,考虑调大 dataHost 的 maxCon。读流量分配是否合理,看各 readHost 的READ_LOAD数字是否贴合 weight 配置。主从切换状态看SWITCH列,值不为 0 时说明发生过切换,这时候要检查主库是否已经恢复并返回时间。
我之前在模拟项目X上线初期,一直是全量读走主库的架构。后来业务量上来,主库 CPU 冲到 70%,才按上面这套配置把 orders 表的读路由拆到从库。结果上线第一天半夜,从库磁盘告警,我下意识去看 show @@datasource,发现某个 readHost 的 READ_LOAD 是 0,而另一个是满的。排查下来是 partition 配置文件里两个从库的 host 名写反了,weight 参数没有按预期分配。从那以后我每次调完 schema.xml 都会重启前先跑一次 EXPLAIN 验证路由,上线后第一屏固定看 show @@datasource 的连接分布,确认读流量按权重落地后再丢开手。Mycat 1.6.7.1 这套配置,只要物理库连接信息正确、分片规则和节点数对齐、防火墙端口放行,运行稳定性是有保障的,后续维护成本远低于自研数据访问层。希望帮到你。
本文还有配套的精品资源,点击获取