阿杰,我帮你整理一份 MyCat 数据库中间件 的全面介绍,包括简介、架构、原理、使用场景和注意事项。


一、MyCat 简介

  • MyCat 是一个 开源的分布式数据库中间件,基于 Java 开发,兼容 MySQL 协议。
  • 主要功能:
    1. 分库分表:将数据水平拆分到多个数据库实例,提高性能和扩展性。
    2. 读写分离:支持主从复制,读请求走从库,写请求走主库。
    3. 分布式事务支持:通过 XA 或 TCC 实现跨库事务。
    4. SQL 路由与合并:支持复杂 SQL 的拆分、路由和结果合并。
  • 适用场景:
    • 高并发访问的 OLTP 系统
    • 数据量超大,需要水平拆分的数据库
    • 多租户 SaaS 系统

二、MyCat 架构

MyCat 采用 中间层架构,位于应用程序与后端数据库之间:

      +----------------+
      |   应用程序      |
      +----------------+
              |
        MyCat 中间件
+--------------------------+
| SQL 路由 | 事务管理 | 缓存 |
+--------------------------+
       /             \
      /               \
+--------+         +--------+
| MySQL1 |         | MySQL2 |
+--------+         +--------+
  • 应用透明访问:应用直接使用 MySQL JDBC 驱动连接 MyCat。
  • SQL 路由:根据配置的分库分表策略,将 SQL 自动路由到对应数据库表。
  • 事务管理:支持本地事务和分布式事务(XA)。
  • 缓存:可配置二级缓存,提升查询性能。

三、MyCat 核心原理

  1. 分库分表规则
    • 支持 哈希分片、范围分片、列表分片
    • SQL 中通过 分片键 路由到具体数据库表
    • 示例:user_id % 4 → 4 个库或表
  2. SQL 路由与拆分
    • 支持 简单 SQL 拆分(如单表查询)
    • 支持 聚合函数、JOIN 的结果合并(部分场景有限制)
  3. 读写分离
    • 主库写操作,自动同步到从库
    • 读操作优先走从库,实现负载均衡
  4. 事务处理
    • 单库事务由 MySQL 处理
    • 跨库事务支持 XA 或应用控制
  5. 连接池与性能优化
    • 内置连接池管理后端数据库连接
    • 支持 SQL 缓存批量操作,提升吞吐量

四、MyCat 使用指南

1. 下载与部署

  • 下载最新版本:MyCat 官网
  • 解压到服务器目录:
tar -zxvf mycat-server-x.x.x.tar.gz
cd mycat-server
  • 修改配置文件:
    • server.xml:监听端口、JDBC 协议设置
    • schema.xml:数据库和分库分表规则
    • rule.xml:分表策略
  • 启动 MyCat:
sh bin/startup.sh

2. 连接 MyCat

  • 使用 MySQL 客户端或 JDBC 直接连接:
mysql -h mycat_host -P 8066 -u myuser -p
  • 端口默认 8066,用户名密码由 server.xml 配置

3. 配置示例(分库分表)

schema.xml

<schema name="test_db" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1,dn2">
    <table name="user" primaryKey="id" dataNode="dn1,dn2" rule="user_rule"/>
</schema>

rule.xml

<rule name="user_rule" type="hash_mod">
    <columns>id</columns>
    <algorithm expression="id % 2" />
    <dataNodes>dn1,dn2</dataNodes>
</rule>
  • user 表根据 id % 2 分配到 dn1dn2 数据节点
  • dn1dn2 对应实际 MySQL 实例

五、注意事项

  1. 兼容性
    • MyCat 尽量兼容 MySQL,但部分 复杂 JOIN、存储过程 支持有限
  2. 分布式事务
    • XA 性能有一定开销,跨库事务要谨慎
  3. 监控和运维
    • 建议配合 日志分析 + 监控系统,及时发现 SQL 慢查询
  4. 分库分表设计
    • 尽量使用 整数或唯一 ID 作为分片键
    • 避免频繁跨库 JOIN

六、总结

  • MyCat 是数据库中间件,用于解决 MySQL 单机瓶颈和扩展性问题
  • 主要功能:分库分表、读写分离、SQL 路由、分布式事务
  • 部署方式:Java 服务,配置 schema 和 rule
  • 应用层透明:应用直接使用 MySQL 协议连接 MyCat,无需改动太多代码

明白阿杰,我帮你写一个 MyCat 分库分表示例 + JDBC 使用示例,演示 自动路由、读写分离,方便直接测试。


一、MyCat 分库分表示例

假设我们有 两个 MySQL 实例

数据节点IP数据库名
dn1127.0.0.1:3306user_db1
dn2127.0.0.1:3306user_db2

我们要将 user 表 根据 id % 2 分配到两个节点:

1. 配置 schema.xml

<schema name="test_db" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1,dn2">
    <table name="user" primaryKey="id" dataNode="dn1,dn2" rule="user_rule"/>
</schema>

2. 配置 rule.xml

<rule name="user_rule" type="hash_mod">
    <columns>id</columns>
    <algorithm expression="id % 2"/>
    <dataNodes>dn1,dn2</dataNodes>
</rule>

3. 数据节点配置 server.xml

<dataNode name="dn1" dataHost="localhost1" database="user_db1"/>
<dataNode name="dn2" dataHost="localhost2" database="user_db2"/>
  • 这里 localhost1localhost2 分别对应两个 MySQL 数据库配置
  • 确保每个数据库中已经创建 user 表结构相同,例如:
CREATE TABLE user (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    age INT
);

二、JDBC 使用 MyCat 示例

应用直接连接 MyCat 端口(默认 8066):

import java.sql.*;

public class MyCatJDBCExample {

    public static void main(String[] args) throws Exception {
        // MyCat 地址和端口
        String url = "jdbc:mysql://127.0.0.1:8066/test_db";
        String user = "mycat_user";
        String password = "123456";

        Connection conn = DriverManager.getConnection(url, user, password);
        Statement stmt = conn.createStatement();

        // 插入示例
        stmt.executeUpdate("INSERT INTO user(id, name, age) VALUES(1, 'Alice', 20)");
        stmt.executeUpdate("INSERT INTO user(id, name, age) VALUES(2, 'Bob', 25)");

        // 查询示例
        ResultSet rs = stmt.executeQuery("SELECT * FROM user");
        while(rs.next()) {
            System.out.println(rs.getInt("id") + " | " +
                               rs.getString("name") + " | " +
                               rs.getInt("age"));
        }

        rs.close();
        stmt.close();
        conn.close();
    }
}

✅ 特点

  1. 自动路由
    • id=1 会路由到 dn1
    • id=2 会路由到 dn2
  2. 读写分离
    • 配置主从数据节点后,查询走从库,写入走主库
    • 对应用透明,无需改动 SQL
  3. 跨库查询注意
    • 简单的单表查询和主键查询没问题
    • 跨库 JOIN 或聚合需要谨慎,性能受限

三、测试步骤

  1. 启动两个 MySQL 实例,分别创建 user_db1user_db2
  2. 启动 MyCat,确保 server.xmlschema.xmlrule.xml 配置正确
  3. 编译运行上述 JDBC 示例程序
  4. 检查两个 MySQL 数据库,确认 INSERT 已根据 id % 2 分配到对应库

明白阿杰,我帮你写一个 MyCat 分库分表 + 读写分离完整测试脚本,使用 Java JDBC,实现以下功能:

  1. 自动生成测试数据
  2. 插入数据,验证分库分表策略(id % 2)
  3. 查询数据,验证读写分离效果
  4. 打印每条数据所在数据库节点(方便验证路由)

import java.sql.*;
import java.util.Random;

public class MyCatTest {

    private static final String URL = "jdbc:mysql://127.0.0.1:8066/test_db";
    private static final String USER = "mycat_user";
    private static final String PASSWORD = "123456";

    public static void main(String[] args) throws Exception {
        Connection conn = DriverManager.getConnection(URL, USER, PASSWORD);
        Statement stmt = conn.createStatement();

        // 1. 创建测试表(如果不存在)
        stmt.executeUpdate("CREATE TABLE IF NOT EXISTS user (" +
                "id INT PRIMARY KEY, name VARCHAR(50), age INT)");

        // 2. 插入随机测试数据
        Random rand = new Random();
        for (int i = 1; i <= 10; i++) {
            String name = "User" + i;
            int age = 18 + rand.nextInt(30);
            stmt.executeUpdate(String.format("INSERT INTO user(id, name, age) VALUES(%d, '%s', %d) " +
                    "ON DUPLICATE KEY UPDATE name='%s', age=%d", i, name, age, name, age));
            System.out.println("插入数据: id=" + i + ", name=" + name + ", age=" + age);
        }

        // 3. 查询数据并打印
        ResultSet rs = stmt.executeQuery("SELECT * FROM user ORDER BY id");
        while (rs.next()) {
            int id = rs.getInt("id");
            String name = rs.getString("name");
            int age = rs.getInt("age");
            System.out.println("查询数据: id=" + id + ", name=" + name + ", age=" + age);
            System.out.println("路由节点推测: " + (id % 2 == 0 ? "dn2" : "dn1"));
        }

        rs.close();
        stmt.close();
        conn.close();
    }
}

使用说明

  1. 准备环境
    • 启动 MyCat,确保配置好两个数据节点 dn1/dn2
    • 确保 MySQL 数据库 user_db1 和 user_db2 已创建
  2. 编译运行 javac MyCatTest.java java -cp .:mysql-connector-java-8.0.36.jar MyCatTest
  3. 验证结果
    • 控制台会打印每条插入和查询数据
    • id % 2 == 0 的数据属于 dn2,否则属于 dn1
    • 可以登录 MySQL 实例,验证数据是否分配正确

特点

  1. 自动生成数据,无需手动插入
  2. 分库分表验证,通过 id % 2 显示路由节点
  3. 读写分离验证
    • 配置主从节点后,查询会走从库,插入走主库
  4. 一次性测试完整流程,方便开发调试