【数据库】MySQL基于MyCAT分库分表

虽然MyCAT中间件几年前就已不再更新,但目前市场上还是有不少存量使用MyCAT分库分表架构的场景,因此有必要了解其核心原理与使用方式:

一、基本介绍和架构

1. MyCAT 定位与核心价值

MyCAT 是基于 MySQL 协议的开源分布式数据库中间件,核心定位是「数据库层的负载均衡与分库分表网关」:

  • 对应用层完全透明:应用只需连接 MyCAT(如同连接普通 MySQL),无需感知底层物理库的分片逻辑;
  • 核心能力:SQL 解析、分片路由、结果聚合、读写分离、故障切换;
  • 解决的核心问题:单库数据量过大(如千万级+)导致的性能瓶颈,实现数据水平拆分(分库分表)。

2. MyCAT 整体架构(分层设计)

各层核心职责:
层级 核心组件 职责说明
接入层 前端连接池、MySQL协议解析 接收应用的MySQL连接请求,兼容MySQL协议,管理前端连接(8066业务端口/9066管理端口)
核心层 SQL解析器 解析SQL语句,提取表名、分片键、操作类型(增删改查)等关键信息
分片路由引擎 根据rule.xml的分片规则,计算SQL应路由到哪些dataNode(数据节点)
结果聚合引擎 将多个物理节点返回的结果集合并、排序、分页,返回统一结果给应用
连接池管理 管理MyCat到后端MySQL的连接池(对应dataHost的maxCon/minCon配置)
数据节点层 dataNode/dataHost 映射到实际的MySQL物理库,执行路由后的SQL,返回结果给核心层

3. MyCAT 与传统数据库架构的对比

架构类型 架构特点 痛点 MyCat 分布式架构 优势
单库单表 所有数据存在一个MySQL实例的一张表 数据量达千万级后查询/写入卡顿 数据拆分到多个MySQL实例的多张表 分散存储压力,提升并发性能
单库多表 同实例内分表,未拆分数据库 实例级瓶颈(CPU/IO/内存) 跨实例分库分表 突破单实例资源限制
应用层分库分表 应用代码硬编码分片规则 代码耦合度高,维护成本高 中间件层统一管理分片规则 应用无感知,规则可动态调整

4. MyCAT 核心设计理念

(1)「逻辑库/逻辑表」与「物理库/物理表」的解耦
  • 逻辑层(对外) :MyCAT 暴露的 DB01(逻辑库)、TB_ORDER(逻辑表)是应用直接操作的对象,与普通 MySQL 库表无差异;
  • 物理层(对内) :逻辑表 TB_ORDER 被拆分到 dn1/dn2/dn3 三个数据节点,对应 3 个 MySQL 实例的 db01.TB_ORDER 物理表;
  • 解耦价值:应用无需修改代码,只需调整 MyCAT 配置即可变更分片规则/物理节点,适配数据量增长。
(2)分片核心:「分片键」与「分片规则」
  • 分片键 :决定数据路由的字段(如 TB_ORDER.id),是分库分表的核心依据;
  • 分片规则 :MyCAT 内置多种规则(如 auto-sharding-long 按长整型范围分片、mod-long 按取模分片、hash-int 哈希分片等);
    • auto-sharding-long 规则:基于 autopartition-long.txt 中的范围配置(如 0-1000000 到 dn1,1000001-2000000 到 dn2 等),将不同 id 范围的数据路由到不同节点;
  • 规则设计原则:分片键需选查询高频字段(如订单ID、用户ID),避免跨节点全表扫描(MyCAT 跨节点聚合性能较差)。
(3)连接池与高可用设计
  • 前端连接池:MyCAT 对应用侧的连接进行管理,默认支持高并发连接;
  • 后端连接池dataHost 配置的 maxCon/minCon 是 MyCAT 到每个 MySQL 实例的连接池大小,避免频繁创建/销毁连接;
  • 高可用dataHostswitchType="1" 开启心跳检测(select user()),当某个 writeHost 宕机时,MyCAT 自动切换到备用节点(若配置),保障服务可用。
(4)全局序列(自增主键)
  • 配置中 TB_ORDER 开启 autoIncrement="true",解决分布式场景下主键自增冲突问题:
    • MyCAT 提供全局序列生成器(如 HttpIncrSequenceHandler),保证不同物理节点的 TB_ORDER.id 全局唯一;
    • 对比原生 MySQL 自增:单实例自增主键无法跨实例保证唯一,MyCAT 全局序列是分布式分表的必备能力。

二、实验节点规划

1. 节点信息表

节点类型 节点名称/IP 端口 作用说明 相关配置关联
MyCAT 服务节点 192.168.31.122 8066(业务)、9066(管理) 部署MyCAT服务,提供逻辑库访问入口,处理分库分表路由、转发SQL请求 server.xml、schema.xml
MySQL 物理节点1 192.168.31.123(dhost1) 3306 存储分片数据节点dn1,对应物理库db01,接收MyCat转发的SQL操作 schema.xml中dn1、dhost1
MySQL 物理节点2 192.168.31.124(dhost2) 3306 存储分片数据节点dn2,对应物理库db01,接收MyCat转发的SQL操作 schema.xml中dn2、dhost2
MySQL 物理节点3 192.168.31.125(dhost3) 3306 存储分片数据节点dn3,对应物理库db01,接收MyCat转发的SQL操作 schema.xml中dn3、dhost3
逻辑库 DB01(MyCat逻辑库) - 对外暴露的统一数据库入口,屏蔽底层物理库差异 server.xml、schema.xml
逻辑表 TB_ORDER(分片表) - 对外暴露的统一数据表,数据按分片规则分布在3个MySQL物理节点的db01库中 schema.xml、rule.xml

说明:MySQL 部署流程不再赘述,以下操作均以已部署好三个 MySQL 单机节点为前提。

2. 实验架构可视化

物理数据库层
MyCat 中间件层
应用层
Java/PHP/Python应用
接入层

8066/9066端口

MySQL协议兼容
核心层

SQL解析+路由+聚合
配置层

schema.xml/server.xml/rule.xml
MySQL节点1

192.168.31.123:3306

db01.TB_ORDER
MySQL节点2

192.168.31.124:3306

db01.TB_ORDER
MySQL节点3

192.168.31.125:3306

db01.TB_ORDER

三、部署与使用

1. MyCAT 目录结构

(1)服务器级目录结构(部署路径)
复制代码
/
├── data/
│   ├── pkg/                # 安装包存放目录
│   │   ├── Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz  # MyCat安装包
│   │   ├── mysql-connector-j-8.0.33.tar.gz                            # MySQL驱动安装包
│   │   ├── mysql-connector-j-8.0.33/                                  # 驱动解压目录
│   │   └── mysql-connector-java-5.1.35.jar                            # 旧驱动备份文件
│   └── mycat/              # MyCat核心目录(解压后根目录)
│       ├── bin/            # 可执行文件目录(启动/停止脚本)
│       ├── catlet/         # 多表联查相关扩展目录(无需重点关注)
│       ├── conf/           # 核心配置文件目录
│       ├── lib/            # 项目依赖包目录(jar包,含MySQL驱动)
│       └── logs/           # 日志文件目录(运行日志、错误日志等)
└── usr/
    └── lib/jvm/            # JDK安装目录(java-1.8.0-openjdk)
(2)MyCAT 核心目录(/data/mycat/)详细结构
复制代码
/data/mycat/
├── bin/                    # 操作脚本目录
│   ├── mycat               # 核心脚本(start/stop/status等操作)
│   └── 其他辅助脚本        # 无需手动修改
├── catlet/                 # 扩展目录
│   └── 自定义catlet相关类  # 多表联查扩展实现,默认无需改动
├── conf/                   # 配置文件核心目录
│   ├── schema.xml          # 逻辑库、逻辑表、数据节点、物理主机配置(核心)
│   ├── schema.xml.bak      # schema.xml备份文件
│   ├── server.xml          # 用户账号、权限、系统参数配置(核心)
│   ├── server.xml.bak      # server.xml备份文件
│   ├── rule.xml            # 分片规则配置文件
│   ├── autopartition-long.txt # 长整型分片规则配置文件
│   ├── schema.dtd          # schema.xml语法约束文件
│   ├── server.dtd          # server.xml语法约束文件
│   └── 其他配置文件        # 如log4j2.xml(日志配置)等
├── lib/                    # 依赖包目录
│   ├── mysql-connector-j-8.0.33.jar  # 替换后的新版MySQL驱动
│   ├── mycat-server-1.6.7.5.jar      # MyCat核心jar包
│   └── 其他第三方依赖jar包            # 如spring、netty等
└── logs/                   # 日志目录
    ├── mycat.log           # MyCat运行日志
    ├── wrapper.log         # 包装器日志
    ├── sql.log             # SQL执行日志
    └── 其他日志文件        # 如慢查询日志、错误日志等
(3)目录核心文件说明
目录路径 核心文件/目录 作用说明
/data/mycat/bin/ mycat 启动、停止、查看MyCat状态的核心脚本,执行./mycat start即可启动服务
/data/mycat/conf/ schema.xml 定义逻辑库、逻辑表、数据节点与物理主机的映射关系,是分库分表核心配置
/data/mycat/conf/ server.xml 配置MyCat登录用户、密码、权限及系统全局参数(如端口、超时时间)
/data/mycat/conf/ rule.xml 定义分片规则名称与具体实现的关联,配合分片配置文件使用
/data/mycat/lib/ mysql-connector-j-8.0.33.jar 连接MySQL物理节点的驱动包,需替换为高版本以兼容新版MySQL
/data/mycat/logs/ mycat.log 记录MyCat运行过程中的关键信息,用于排查启动失败、SQL路由异常等问题
(4)关键补充说明
  1. 目录权限 :MyCAT相关目录(尤其是lib、logs)需保证运行用户有读写权限,文中已通过chmod 777设置驱动包权限;
  2. 核心端口:MyCAT默认占用8066(业务访问端口,用于mysql客户端连接)、9066(管理端口,用于运维管理);
  3. 配置备份:修改核心配置文件(schema.xml、server.xml)前,建议按日期备份(如.20251206后缀),便于故障回滚。

2. 安装MyCAT

(1)安装JDK(MyCAT运行依赖)
sh 复制代码
dnf install -y java-1.8.0-openjdk java-1.8.0-openjdk-devel
java -version
(2)安装MyCAT主程序
sh 复制代码
mkdir /data/pkg
cd /data/pkg
wget https://github.com/MyCATApache/Mycat-Server/releases/download/Mycat-server-1675-release/Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz
tar -zxvf ./Mycat-server-1.6.7.5-release-20200422133810-linux.tar.gz -C /data/

cd /data/mycat
mkdir ./logs
ll 
(3)替换高版本MySQL驱动(解决兼容性问题)
sh 复制代码
cd /data/pkg/
ll /data/mycat/lib/mysql-connector-java-*

# 备份旧驱动
mv /data/mycat/lib/mysql-connector-java-5.1.35.jar /data/pkg/

# 下载并解压新版驱动
wget https://downloads.mysql.com/archives/get/p/3/file/mysql-connector-j-8.0.33.tar.gz
tar -zxvf mysql-connector-j-8.0.33.tar.gz
cp /data/pkg/mysql-connector-j-8.0.33/mysql-connector-j-8.0.33.jar /data/mycat/lib/

# 修改权限
chmod 777 /data/mycat/lib/mysql-connector-java-*
ll /data/mycat/lib/mysql-connector-java-*

3. 配置MyCAT

(1)配置schema.xml(核心映射关系)
sh 复制代码
cd /data/mycat/conf
cp /data/mycat/conf/schema.xml /data/mycat/conf/schema.xml.bak
vi /data/mycat/conf/schema.xml

配置内容:

xml 复制代码
<?xml version="1.0"?>
<!DOCTYPE mycat:schema SYSTEM "schema.dtd">
<mycat:schema xmlns:mycat="http://io.mycat/">

        <schema name="DB01" checkSQLschema="true" sqlMaxLimit="100" randomDataNode="dn1">
                <table name="TB_ORDER" primaryKey="id" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" autoIncrement="true" fetchStoreNodeByJdbc="true">
                </table>
        </schema>
        <dataNode name="dn1" dataHost="dhost1" database="db01" />
        <dataNode name="dn2" dataHost="dhost2" database="db01" />
        <dataNode name="dn3" dataHost="dhost3" database="db01" />
        
        <dataHost name="dhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="master" url="jdbc:mysql://192.168.31.123:3306?useSSL=false&amp;serverTimezone=Asia/Shanghai" user="root" password="root.COM2025*">
                </writeHost>
        </dataHost>
        
        <dataHost name="dhost2" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="master" url="jdbc:mysql://192.168.31.124:3306?useSSL=false&amp;serverTimezone=Asia/Shanghai" user="root" password="root.COM2025*">
                </writeHost>
        </dataHost>
        
        <dataHost name="dhost3" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc" switchType="1"  slaveThreshold="100">
                <heartbeat>select user()</heartbeat>
                <writeHost host="master" url="jdbc:mysql://192.168.31.125:3306?useSSL=false&amp;serverTimezone=Asia/Shanghai" user="root" password="root.COM2025*">
                </writeHost>
        </dataHost>
</mycat:schema>
(2)MySQL用户认证插件调整(兼容MyCAT)
sql 复制代码
-- 登录MySQL,修改用户认证插件为mysql_native_password
ALTER USER 'root'@'%' IDENTIFIED WITH mysql_native_password BY 'root.COM2025*';
FLUSH PRIVILEGES;
(3)配置server.xml(用户与权限)
sh 复制代码
cd /data/mycat/conf
cp /data/mycat/conf/server.xml /data/mycat/conf/server.xml.bak
vi /data/mycat/conf/server.xml

核心修改内容(仅保留用户密码和schema相关):

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mycat:server SYSTEM "server.dtd">
<mycat:server xmlns:mycat="http://io.mycat/">
        <system>
        <property name="nonePasswordLogin">0</property>
        <property name="ignoreUnknownCommand">0</property>
        <property name="useHandshakeV10">1</property>
        <property name="removeGraveAccent">1</property>
        <property name="useSqlStat">0</property>
        <property name="useGlobleTableCheck">0</property>
        <property name="sqlExecuteTimeout">300</property>
        <property name="sequenceHandlerType">1</property>
        <property name="sequnceHandlerPattern">(?:(\s*next\s+value\s+for\s*MYCATSEQ_(\w+))(,|\)|\s)*)+</property>
        <property name="subqueryRelationshipCheck">false</property>
        <property name="sequenceHanlderClass">io.mycat.route.sequence.handler.HttpIncrSequenceHandler</property>
        <property name="processorBufferPoolType">0</property>
        <property name="handleDistributedTransactions">0</property>
        <property name="useOffHeapForMerge">0</property>
        <property name="memoryPageSize">64k</property>
        <property name="spillsFileBufferSize">1k</property>
        <property name="useStreamOutput">0</property>
        <property name="systemReserveMemorySize">384m</property>
        <property name="useZKSwitch">false</property>
        <property name="strictTxIsolation">false</property>
        <property name="parallExecute">0</property>
        </system>

        <user name="root" defaultAccount="true">
                <property name="password">root.COM2025*</property>
                <property name="schemas">DB01</property>
        </user>

        <user name="user">
                <property name="password">123456</property>
                <property name="schemas">DB01</property>
                <property name="readOnly">true</property>
        </user>

</mycat:server>

4. 启动与管理MyCAT

(1)基础启停命令
sh 复制代码
cd /data/mycat/
./bin/mycat start 
./bin/mycat stop 
(2)配置systemctl服务(便捷管理)

创建 /usr/lib/systemd/system/mycat.service 文件:

ini 复制代码
[Unit]
Description=MyCat Service
After=network.target

[Service]
Type=forking
ExecStart=/data/mycat/bin/mycat start
ExecStop=/data/mycat/bin/mycat stop
ExecReload=/data/mycat/bin/mycat restart
User=root  # 可根据实际运行用户调整
Restart=on-failure

[Install]
WantedBy=multi-user.target

核心systemctl命令:

sh 复制代码
# 重新加载服务配置
systemctl daemon-reload

# 启动
systemctl start mycat

# 停止
systemctl stop mycat

# 重启
systemctl restart mycat

# 设置开机自启
systemctl enable mycat

# 查看状态
systemctl status mycat

5. 访问与验证MyCAT

(1)登录MyCAT
sh 复制代码
mysql -h 192.168.31.122 -P 8066 -uroot -p"root.COM2025*"
(2)确认连接信息
sql 复制代码
\s
--------------
mysql  Ver 8.4.0 for Linux on x86_64 (MySQL Community Server - GPL)

Connection id:          1
Current database:       db01
Current user:           root@192.168.31.122
SSL:                    Not in use
Current pager:          stdout
Using outfile:          ''
Using delimiter:        ;
Server version:         5.6.29-mycat-1.6.7.5-release-20200422133810 MyCat Server (OpenCloudDB)
Protocol version:       10
Connection:             192.168.31.122 via TCP/IP
Server characterset:    utf8mb4
Db     characterset:    utf8mb4
Client characterset:    utf8mb4
Conn.  characterset:    utf8mb4
TCP port:               8066
Binary data as:         Hexadecimal
--------------
(3)验证逻辑库/表并创建物理表
sql 复制代码
-- 查看逻辑库
show databases;

-- 切换到逻辑库
use DB01;

-- 查看逻辑表
show tables;

-- 创建分片表
CREATE TABLE TB_ORDER (
id BIGINT(20) NOT NULL,
title VARCHAR(100) NOT NULL,
PRIMARY KEY (id)
) ENGINE=INNODB DEFAULT CHARSET=utf8 ;

-- 插入测试数据
INSERT INTO TB_ORDER(id,title) VALUES(1,'goods1');
INSERT INTO TB_ORDER(id,title) VALUES(2,'goods2');
INSERT INTO TB_ORDER(id,title) VALUES(3,'goods3');
INSERT INTO TB_ORDER(id,title) VALUES(1000000,'goods1000000 ');
INSERT INTO TB_ORDER(id,title) VALUES(4000000,'goods4000000');
INSERT INTO TB_ORDER(id,title) VALUES(4000001,'goods4000001');
INSERT INTO TB_ORDER(id,title) VALUES(8000000,'goods8000000');
INSERT INTO TB_ORDER(id,title) VALUES(10000001,'goods10000001');
INSERT INTO TB_ORDER(id,title) VALUES(15000001,'goods15000001'); -- 超出规则范围

-- 查询数据(验证分片效果)
SELECT * FROM TB_ORDER;

-- 查看分片规则配置
-- 执行以下Shell命令
cd /data/mycat/conf/
cat ./rule.xml
cat ./autopartition-long.txt

四、配置文件详解

1. schema标签

xml 复制代码
<schema name="DB01" checkSQLschema="true" sqlMaxLimit="100">
    <table name="TB_ORDER" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>
作用说明
  • schema标签用于定义MyCAT实例中的逻辑库
  • 一个MyCAT实例可包含多个逻辑库;
  • MyCAT的逻辑库等同于MySQL中的database概念,操作表时需切换到对应逻辑库。
核心属性
  • name:指定自定义的逻辑库库名;
  • checkSQLschema :SQL语句中指定数据库名时,执行是否自动去除
    • true:自动去除;
    • false:不自动去除;
  • sqlMaxLimit:未指定limit的列表查询,默认返回的记录条数。

2. schema标签的table子标签

xml 复制代码
<schema name="DB01" checkSQLschema="true" sqlMaxLimit="100">
    <table name="TB_ORDER" dataNode="dn1,dn2,dn3" rule="auto-sharding-long" />
</schema>
作用说明
  • table标签用于定义MyCAT逻辑库(schema)下的逻辑表
  • 所有需要拆分的表都需在此标签中定义。
核心属性
  • name:逻辑表的表名,在当前逻辑库下唯一;
  • dataNode:逻辑表所属的dataNode,需与dataNode标签的name对应;多个dataNode用逗号分隔;
  • rule:分片规则名称,该名称在rule.xml中定义;
  • primaryKey:逻辑表对应真实表的主键;
  • type :逻辑表类型,可选值:
    • 不配置:默认是普通表;
    • global:全局表。

3. dataNode标签

xml 复制代码
<dataNode name="dn1" dataHost="dhost1" database="db01" />
<dataNode name="dn2" dataHost="dhost2" database="db01" />
<dataNode name="dn3" dataHost="dhost3" database="db01" />
作用说明
  • dataNode标签用于定义MyCAT中的数据节点(即数据分片);
  • 一个dataNode对应一个独立的数据分片。
核心属性
  • name:数据节点的名称;
  • dataHost:数据库实例的主机名称,需与dataHost标签的name属性对应;
  • database:该分片对应的实际数据库名称。

4. dataHost标签

xml 复制代码
<dataHost name="dhost1" maxCon="1000" minCon="10" balance="0" writeType="0" dbType="mysql" dbDriver="jdbc">
    <heartbeat>select user()</heartbeat>
    <writeHost host="master" url="jdbc:mysql://192.168.200.210:3306?useSSL=false&amp;serverTimezone=Asia/Shanghai&amp;characterEncoding=utf8" user="root" password="1234">
    </writeHost>
</dataHost>
作用说明
  • 该标签是MyCAT逻辑库的底层配置;
  • 用于定义具体数据库实例、读写分离规则、心跳检测语句
核心属性
  • name:唯一标识,供上层标签(如dataNode)引用;
  • maxCon/minCon:数据库连接池的最大/最小连接数;
  • balance:负载均衡策略,可选值为0、1、2、3;
  • writeType :写操作的分发方式
    • 0:写操作优先转发到第一个writeHost,挂了则切换到下一个;
    • 1:写操作随机分发到已配置的writeHost;
  • dbDriver :数据库驱动类型,支持nativejdbc

五、总结

1. 核心关键点

  • 架构核心:MyCAT 采用「中间件网关」架构,通过逻辑层屏蔽物理层的分库分表细节,实现应用无感知的分布式数据存储;
  • 配置核心schema.xml 定义逻辑-物理映射关系,rule.xml 定义分片规则,server.xml 定义用户权限,三者共同支撑分库分表逻辑;
  • 设计关键:分片键选择、规则匹配、连接池配置是 MyCAT 性能和可用性的核心,需结合业务查询场景设计(避免跨节点全表扫描)。

2. 生产落地建议

  • 分片键优先选择「查询高频、更新低频」的字段(如订单ID、用户ID);
  • 对跨节点的聚合查询(如 count(*)sum())做缓存优化,避免频繁触发 MyCAT 全节点扫描;
  • 定期监控 MyCAT 日志(mycat.log/sql.log),排查慢SQL和路由异常;
  • 高可用部署:MyCAT 建议双节点部署(避免单点故障),后端 MySQL 建议主从架构,配合 dataHostbalance 配置实现读写分离。
相关推荐
哈里谢顿2 小时前
千万级订单表新增字段应该如何做?操作小结
mysql
虹科网络安全2 小时前
艾体宝洞察 | 生成式AI上线倒计时:Redis如何把“延迟”与“幻觉”挡在生产线之外?
数据库·人工智能·redis
JIngJaneIL2 小时前
基于java+ vue家庭理财管理系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot
小曹要微笑2 小时前
MySQL的TRIM函数
android·数据库·mysql
smileNicky2 小时前
2025 技术创作与实战:深耕数据库、中间件与 AI 应用的进阶之路
数据库·人工智能·中间件
l1t2 小时前
一个postgresql奇怪慢查询现象的原因和解决
数据库·sql·postgresql·性能优化
IT技术分享社区3 小时前
MySQL事件调度器:深入解析与工作原理
数据库·mysql·程序员
老华带你飞3 小时前
电商系统|基于java + vue电商系统(源码+数据库+文档)
java·开发语言·前端·数据库·vue.js·spring boot·后端
微爱帮监所写信寄信3 小时前
微爱帮监狱寄信寄信信件草稿箱技术设计文档
数据库