MySQL 主从复制与 MyCat 分库分表实战详解

一、引言

在当今互联网高并发、大数据量的业务场景下,单一 MySQL 实例已无法满足性能与可用性需求。主从复制 实现了数据读写分离与高可用,MyCat 分库分表则突破了单表数据量的存储瓶颈,二者结合是构建大型分布式数据库系统的经典方案。

本文将从原理、环境搭建、实战配置到效果验证,完整讲解 MySQL 主从复制与 MyCat 分库分表的实现流程,帮助开发者快速掌握这一核心技术。


二、核心原理剖析

2.1 MySQL 主从复制原理

MySQL 主从复制(Master-Slave Replication)是基于 ** 二进制日志(Binary Log)** 实现的异步数据同步机制,核心流程如下:

  1. 主库(Master):当执行 INSERT/UPDATE/DELETE 等写操作时,会将数据变更记录到二进制日志(Binary Log)中。
  2. 从库(Slave) :通过 I/O 线程连接主库,请求获取指定位置之后的二进制日志,并写入本地中继日志(Relay Log)
  3. 从库(Slave):通过 SQL 线程读取中继日志,重放其中的 SQL 操作,从而实现与主库的数据一致。

主从复制的核心作用:

  • 读写分离:主库处理写请求,从库分担读请求,提升系统并发能力。
  • 数据备份:从库可作为主库的实时备份,降低数据丢失风险。
  • 故障转移:主库宕机时,可快速将从库提升为新主库,保证服务可用性。

2.2 MyCat 分库分表原理

MyCat 是一个开源的分布式数据库中间件,它实现了数据库分库分表读写分离,对应用层透明,让开发者可以像操作单库一样操作分布式数据库集群。

核心特性:

  • 水平分表:将一张大表按规则(如范围、哈希、取模)拆分到多个数据库实例中,解决单表数据量过大问题。
  • 垂直分库:将不同业务模块的表拆分到不同数据库,实现业务解耦与资源隔离。
  • 读写分离:结合 MySQL 主从复制,自动将写请求路由到主库,读请求路由到从库。
  • 跨库 Join:支持在分库分表场景下执行多表关联查询,简化开发复杂度。

三、实验环境准备

3.1 服务器规划

本次实验采用 3 台 CentOS 7 服务器,具体角色分配如下:

主机名 IP 地址 角色 安装软件
Mysql-server 192.168.10.101 MySQL 主库(Master) MySQL 5.7.36
Slave-server 192.168.10.102 MySQL 从库(Slave) MySQL 5.7.36
Mycat-server 192.168.10.103 MyCat 中间件节点 JDK 8、MyCat 1.6

3.2 基础环境配置

  1. 关闭防火墙与 SELinux

    复制代码
    systemctl stop firewalld
    systemctl disable firewalld
    setenforce 0
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/' /etc/selinux/config
  2. 配置主机名与 hosts 解析

    复制代码
    # 在各节点分别设置主机名
    hostnamectl set-hostname Mysql-server
    hostnamectl set-hostname Slave-server
    hostnamectl set-hostname Mycat-server
    
    # 编辑/etc/hosts,添加以下内容
    192.168.10.101 Mysql-server
    192.168.10.102 Slave-server
    192.168.10.103 Mycat-server
  3. 同步系统时间

    复制代码
    yum install -y ntpdate
    ntpdate cn.pool.ntp.org

四、MySQL 主从复制实战

4.1 安装 MySQL 5.7.36

在 ** 主库(Mysql-server)从库(Slave-server)** 上执行相同安装步骤:

  1. 下载并安装 MySQL YUM 源

    复制代码
    wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm
    rpm -ivh mysql57-community-release-el7-11.noarch.rpm
  2. 安装 MySQL 服务

    复制代码
    yum install -y mysql-community-server
  3. 启动 MySQL 并设置开机自启

    复制代码
    systemctl start mysqld
    systemctl enable mysqld
  4. 获取初始密码并修改

    复制代码
    grep 'temporary password' /var/log/mysqld.log
    mysql -uroot -p
    ALTER USER 'root'@'localhost' IDENTIFIED BY 'Root@123';

4.2 配置主库(Master)

  1. 编辑 MySQL 配置文件/etc/my.cnf

    复制代码
    [mysqld]
    datadir=/var/lib/mysql
    socket=/var/lib/mysql/mysql.sock
    server-id=101  # 唯一ID,主库为101,从库为102
    log-bin=mysql-bin  # 开启二进制日志
    binlog-format=ROW  # 推荐使用ROW模式,数据一致性更高
    expire_logs_days=7  # 日志保留7天
  2. 重启 MySQL 服务

    复制代码
    systemctl restart mysqld
  3. 创建用于复制的账号

    复制代码
    GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.10.%' IDENTIFIED BY 'Repl@123';
    FLUSH PRIVILEGES;
  4. 查看主库状态

    复制代码
    SHOW MASTER STATUS;

    记录下File(如mysql-bin.000001)和Position(如154),后续从库配置需要用到。

4.3 配置从库(Slave)

  1. 编辑 MySQL 配置文件/etc/my.cnf

    复制代码
    [mysqld]
    datadir=/var/lib/mysql
    socket=/var/lib/mysql/mysql.sock
    server-id=102  # 唯一ID,不能与主库相同
    relay-log=relay-bin  # 开启中继日志
    read_only=1  # 设置从库为只读(可选,保证数据一致性)
  2. 重启 MySQL 服务

    复制代码
    systemctl restart mysqld
  3. 配置主从同步

    复制代码
    CHANGE MASTER TO
    MASTER_HOST='Mysql-server',
    MASTER_USER='repl',
    MASTER_PASSWORD='Repl@123',
    MASTER_LOG_FILE='mysql-bin.000001',  # 主库SHOW MASTER STATUS结果
    MASTER_LOG_POS=154;  # 主库SHOW MASTER STATUS结果
  4. 启动从库复制线程

    复制代码
    START SLAVE;
  5. 验证主从状态

    复制代码
    SHOW SLAVE STATUS\G

    Slave_IO_RunningSlave_SQL_Running均为Yes,则表示主从复制配置成功。

4.4 主从复制效果验证

  1. 在主库创建测试数据库和表

    复制代码
    CREATE DATABASE testdb;
    USE testdb;
    CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
    INSERT INTO user (name) VALUES ('Tom'), ('Jerry');
  2. 在从库查询验证

    复制代码
    USE testdb;
    SELECT * FROM user;

    若能查询到主库插入的数据,则说明主从复制生效。


五、MyCat 分库分表实战

5.1 安装 MyCat

Mycat-server节点上执行安装步骤:

  1. 安装 JDK 8

    复制代码
    yum install -y java-1.8.0-openjdk-devel
  2. 下载并解压 MyCat

    复制代码
    wget http://dl.mycat.org.cn/1.6-RELEASE/Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz
    tar -zxvf Mycat-server-1.6-RELEASE-20161028204710-linux.tar.gz -C /usr/local/
  3. 配置环境变量

    复制代码
    echo 'export MYCAT_HOME=/usr/local/mycat' >> /etc/profile
    echo 'export PATH=$PATH:$MYCAT_HOME/bin' >> /etc/profile
    source /etc/profile

5.2 MyCat 核心配置

MyCat 的核心配置文件位于$MYCAT_HOME/conf目录下,主要包括:

  • server.xml:配置 MyCat 服务、用户权限、端口等。
  • schema.xml:配置逻辑库、逻辑表、数据节点和数据主机。
  • rule.xml:配置分表规则。
5.2.1 配置server.xml
复制代码
<user name="root">
    <property name="password">Root@123</property>
    <property name="schemas">TESTDB</property>  <!-- 逻辑库名 -->
</user>
<user name="user">
    <property name="password">User@123</property>
    <property name="schemas">TESTDB</property>
    <property name="readOnly">true</property>  <!-- 只读用户 -->
</user>
5.2.2 配置schema.xml

水平分表 为例,将user表按id取模拆分到主库和从库的两个数据库中:

复制代码
<schema name="TESTDB" checkSQLschema="false" sqlMaxLimit="100">
    <!-- 逻辑表user,分表规则为mod-long -->
    <table name="user" dataNode="dn1,dn2" rule="mod-long" />
</schema>

<!-- 数据节点,对应真实数据库 -->
<dataNode name="dn1" dataHost="localhost1" database="testdb1" />
<dataNode name="dn2" dataHost="localhost1" database="testdb2" />

<!-- 数据主机,对应MySQL实例 -->
<dataHost name="localhost1" maxCon="1000" minCon="10" balance="1"
          writeType="0" dbType="mysql" dbDriver="native" switchType="1"  slaveThreshold="100">
    <heartbeat>select user()</heartbeat>
    <!-- 写节点:主库 -->
    <writeHost host="hostM1" url="192.168.10.101:3306" user="root" password="Root@123">
        <!-- 读节点:从库,实现读写分离 -->
        <readHost host="hostS1" url="192.168.10.102:3306" user="root" password="Root@123" />
    </writeHost>
</dataHost>
5.2.3 配置rule.xml
复制代码
<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>

5.3 初始化分库环境

在 ** 主库(Mysql-server)** 上创建分库对应的真实数据库:

复制代码
CREATE DATABASE testdb1;
CREATE DATABASE testdb2;

-- 在两个库中创建相同结构的user表
USE testdb1;
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));
USE testdb2;
CREATE TABLE user (id INT PRIMARY KEY AUTO_INCREMENT, name VARCHAR(20));

5.4 启动 MyCat 并验证

  1. 启动 MyCat 服务

    复制代码
    mycat start
  2. 连接 MyCat

    复制代码
    mysql -uroot -pRoot@123 -h127.0.0.1 -P8066  # MyCat默认端口为8066
  3. 测试分库分表

    复制代码
    USE TESTDB;
    INSERT INTO user (id, name) VALUES (1, 'Alice'), (2, 'Bob'), (3, 'Charlie'), (4, 'David');
  4. 验证数据分布

    • 在主库查询testdb1.userid为 1、3 的数据。
    • 在主库查询testdb2.userid为 2、4 的数据。
    • 说明数据已按id%2的规则成功拆分到两个库中。
  5. 测试读写分离

    复制代码
    SELECT * FROM user;  # 读请求会自动路由到从库
    INSERT INTO user (id, name) VALUES (5, 'Eve');  # 写请求会路由到主库

    通过查看从库日志或SHOW SLAVE STATUS,可验证读请求由从库处理,写请求由主库处理并同步到从库。


六、常见问题与解决方案

6.1 主从复制异常

  1. Slave_IO_Running 为 No

    • 原因:网络不通、主库账号密码错误、MASTER_LOG_FILEMASTER_LOG_POS配置错误。
    • 解决:检查网络连通性,确认复制账号权限,重新执行CHANGE MASTER TO
  2. Slave_SQL_Running 为 No

    • 原因:从库执行 SQL 出错(如主键冲突、表不存在)。

    • 解决:

      复制代码
      STOP SLAVE;
      SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1;  # 跳过1个错误事务
      START SLAVE;

      或手动修复数据后重启复制。

6.2 MyCat 连接失败

  1. 无法连接 MyCat(8066 端口)

    • 原因:防火墙未开放端口、MyCat 未启动、配置文件语法错误。
    • 解决:检查防火墙规则,执行mycat status查看状态,检查conf下 XML 文件语法。
  2. 分表查询无结果

    • 原因:分库未创建、表结构不一致、分表规则配置错误。
    • 解决:确认各分库表结构相同,检查schema.xmlrule.xml配置。

七、总结与展望

本文详细讲解了 MySQL 主从复制与 MyCat 分库分表的核心原理与实战流程,通过搭建实验环境,实现了读写分离水平分表,有效解决了高并发与大数据量场景下的数据库性能瓶颈。

核心收获

  • 掌握了 MySQL 主从复制的配置与故障排查方法。
  • 理解了 MyCat 中间件的分库分表与读写分离机制。
  • 具备了构建分布式数据库集群的实战能力。

未来展望

  • 可进一步研究半同步复制、** 组复制(MGR)** 等高级复制技术,提升数据一致性。
  • 结合Sharding-JDBC等其他分库分表中间件,对比不同方案的优缺点。
  • 引入监控告警系统(如 Prometheus+Grafana),实现对数据库集群的可视化监控。
相关推荐
weixin_458580124 小时前
php怎么处理跨域请求_php如何设置header解决跨域问题详解
jvm·数据库·python
m0_734949794 小时前
CSS 背景图片无法加载的常见原因与正确写法详解
jvm·数据库·python
2301_815279524 小时前
mysql如何使用yum安装mysql_配置官方yum源与自动安装
jvm·数据库·python
档案宝档案管理4 小时前
智慧档案管理系统是什么?档案宝功能深度解析
大数据·数据库·人工智能·档案管理
weixin_458580124 小时前
MySQL跨版本迁移数据格式不兼容_使用mysqldump全量导出导入
jvm·数据库·python
绩隐金4 小时前
SQL Server 性能优化实战(第七期):内存架构——缓冲池、计划缓存与内存配置
数据库
Greyson14 小时前
SQL触发器在导入大文件时如何跳过_使用禁用触发器语句导入
jvm·数据库·python
2401_887724504 小时前
Redis怎样统计独立访客UV_基于Set的SADD指令天然去重特性
jvm·数据库·python
MeAT ITEM4 小时前
maven导入spring框架
数据库·spring·maven
RATi GORI4 小时前
SQL中的DISTINCT、SQL DISTINCT详解、DISTINCT的用法、DISTINCT注意事项
java·数据库·sql