MySQL 主从复制 + MyCat 读写分离 — 原理详解与实战
一、前言
二、关键原理
2.1 二进制日志(binlog)与三种格式
2.2 复制的"两日志、三线程"与事务边界
2.3 复制模式:异步 / 半同步 / 同步
2.4 复制延迟的主要成因
2.5 常见复制陷阱与注意点
2.6 读写分离要点
三、实战环境与配置
3.1 Master 示例 my.cnf
3.2 Slave 示例 my.cnf
3.3 主从复制测试
四、用 MyCat 实现读写分离
4.1 MyCat 简要介绍
4.2 MyCat 安装与配置步骤详解
4.2.1 下载与解压
4.2.2 创建专用用户并授权
4.2.3 目录结构说明
4.2.4 配置 Java 环境
4.2.5 配置 MyCat 环境变量
4.2.6 配置主机名解析(可选)
4.3 MyCat 关键配置详解
4.3.1 配置 server.xml
4.3.2 配置 schema.xml
4.3.3 关键参数详解
4.3.4 配置主/从库(如做完主从复制只需执行以下命令)
4.3.5 在MyCat端添加虚拟Ip用于测试
4.4 MyCat 启动与验证
4.4.1 启动 MyCat
4.4.2 查看启动状态
4.4.3 查看日志
4.4.4 连接测试
4.4.5 测试读写分离
4.5 MyCat 配置常见易错点与解决方案
4.5.1 XML 格式错误
4.5.2 数据库连接配置错误
4.5.3 权限配置问题
4.5.4 心跳检测配置不当
4.5.5 负载均衡策略选择不当
4.5.6 连接池配置问题
4.5.7 字符集配置不一致
4.5.8 防火墙和网络配置
4.6 MyCat 与事务/一致性
五、实验注意事项
六、常见故障与排查命令(快捷参考)
七、监控、备份、告警与安全
7.1 监控 & 告警
7.2 备份与恢复
7.3 安全
八、性能与可靠性调优建议
九、快速实验流程
十、结语与后续建议
附录:MyCat 常用管理命令
一、前言
随着业务增长,单台 MySQL 很容易成为瓶颈——同时在"安全性 / 高可用 / 高并发"上难以兼顾。常用解决思路是:
-
用 主从复制 做数据冗余与扩展;
-
在此基础上用 读写分离(读走从库、写走主库)分担读负载。
本文先把复制机制、binlog、事务边界等关键原理讲清楚,再给出基于 MyCat 的实战部署与注意事项。
二、关键原理
以下是理解主从复制与读写分离必须掌握的核心概念与工作流程。
2.1 二进制日志(binlog)与三种格式
MySQL 的 binlog 记录会导致数据变更的事件,主从复制依赖它来把变更传给从库。三种常见格式:
-
STATEMENT(语句复制):记录 SQL 语句(例如
UPDATE t SET x=x+1 WHERE id=1
)。优点:日志小;缺点:非确定性语句(含 NOW(), RAND(), user-defined variable 等)或依赖环境的语句在从库上可能得不到相同结果,容易导致数据不同步或冲突。 -
ROW(行复制):记录受影响的每一行具体变更("前值/后值"或"后值")。优点:确定性高,从库能精确重放,适合复杂/并行复制场景;缺点:binlog 更大。
-
MIXED(混合):MySQL 会在两者间自动选择(复杂或不安全的语句用行复制)。
建议:生产环境常用 ROW
(或 MIXED),特别是有并行复制或高一致性要求时。
2.2 复制的"两日志、三线程"与事务边界
主从复制主要流程(高层):
-
主库(Master):事务提交时,会把变更按 binlog 格式写入 binlog(这是主库复制的"源"),然后事务提交完成(写 binlog 与事务提交的顺序、durability 设置影响安全性)。
-
从库(Slave):
-
I/O 线程:连接 Master,读取 Master 的 binlog 并写入本地的 relay log(中继日志)。
-
SQL 线程:读取 relay log 并在从库上执行/应用这些事件,更新从库数据。
-
注意:在传统异步复制中,从库的应用是串行的(单线程执行 relay log 事件),这会成为复制延迟的瓶颈。MySQL 的并行复制(
slave_parallel_workers
)可以在一定条件下并发重放事务,从而提高从库吞吐。
事务边界与一致性:
-
Binlog 的写入点(master 的 binlog file/pos)是复制的定位点。
-
若使用 GTID(全局事务 ID),主从切换与定位更简单、安全。GTID 可以让 failover 更方便,但需要配置一致性(
gtid_mode=ON
等)。
2.3 复制模式:异步 / 半同步 / 同步
-
异步复制:Master 写完 binlog 就返回,不等待任何从库确认。优点:延迟低、性能高;缺点:主库宕机可能导致已提交的事务未被任何从库持有(有数据丢失风险)。
-
半同步复制(semi-sync):Master 在提交后会等待至少一个从库确认已经接收到并写入中继日志(而不是等待从库执行),以减少数据丢失风险。若超时,通常回退为异步模式。
-
同步复制:要求变更事实上被从库接收并执行完成后 Master 才返回(强一致性,但可显著影响延迟)。
现实常用:异步为默认 +(可选)半同步来折中。MySQL 5.5+ 提供半同步插件,5.7+ 对"无损复制"机制也做好了改进。
2.4 复制延迟的主要成因
-
主库写入、binlog 生成过快,从库 I/O 跟不上;
-
从库执行(SQL 线程)单线程瓶颈,尤其是大量 DDL 或复杂事务;
-
网络延迟或带宽受限;
-
从库资源不足(CPU、内存、磁盘 IO);
-
不当的 binlog_format 或不确定性语句 导致额外开销。
2.5 常见复制陷阱与注意点
-
非确定性语句(例如
UUID()
,NOW()
,RAND()
)在 STATEMENT 模式下会导致主从不同步 → 优先使用 ROW / MIXED; -
AUTO_INCREMENT:多主或分布式写入场景要处理好
auto_increment_increment/offset
,避免主从写入冲突; -
临时表:本地临时表不会出现在 binlog 中(或行为不一致),慎用在复制路径依赖的逻辑中;
-
事务隔离与读一致性:读写分离可能导致"读到旧数据"(read-after-write 问题),需要在应用层或代理层做"读你的写"保障;
-
DDL 操作:某些 DDL 在从库上执行可能阻塞复制或需要特殊操作(建议在低峰并谨慎进行)。
2.6 读写分离要点
-
基本策略:所有写走 Master,读走 Slave;借助复制把数据同步到从库。
-
读写的一致性(Read-after-Write)问题:如果应用在同一会话刚写完数据就读,读到的可能是旧数据(因为从库未应用该事务)。解决方案包括:
-
会话粘性(sticky sessions):在写操作后的同一会话把读请求路由回主库,直到确认复制完成或在事务内读取;
-
短时间内读回主库(写后短时间内强制到主库读);
-
检查复制延迟(代理判断 slave 是否落后到某个 binlog pos,若落后则读主库);
-
使用半同步或 GTID 辅助保证一致性;
-
业务层补偿逻辑(允许最终一致性而不要求强一致性)。
-
-
事务与代理:代理层(如 MyCat)需能识别事务边界(BEGIN/COMMIT)并把事务内的读写路由一致地发往同一后端,以避免跨节点事务不一致问题。不同中间件对事务支持能力不同,部署前需验证。
三、实战环境与配置
网络 / 主机规划
-
Master:
192.168.114.50
-
Slave1:
192.168.114.251
-
Slave2:
192.168.114.252
-
MyCat(代理):
192.168.114.180
(端口 8066) -
客户端 / 测试机:
192.168.114.253
实验环境建议在同一二层网络(同机房 / 同 VLAN)完成,避免跨机房网络延迟带来的假阳性问题。
3.1 Master 示例 my.cnf
text
[mysqld] server_id = 1 #主服务器id为1(不可重复) log_bin = master-bin #开启二进制日志文件(之后生成的日志名为master-bin) binlog_format = MIXED # 推荐 ROW 或 MIXED log_slave_updates = true #开启从服务器日志同步 重启服务 [root@master ~]# systemctl restart mysqld 配置规则 [root@master ~]# mysql -uroot -p Enter password: Welcome to the MySQL monitor. Commands end with ; or \g.
授权复制用户(在 Master 上):
text
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'192.168.114.%' IDENTIFIED BY '123456'; FLUSH PRIVILEGES; SHOW MASTER STATUS;
3.2 Slave 示例 my.cnf
text
[mysqld] #开启二进制日志文件 log-bin=master-bin #设置server id为22,slave2 为23 server_id = 22 #从主服务器上同步日志文件记录到本地 relay-log=relay-log-bin #定义relay-log的位置和名称(index索引) relay-log-index=slave-relay-bin.index
注意:改完配置文件要记得systemctl restart mysqld.service重启服务
在 Slave 上设置 master info 并启动复制:
text
CHANGE MASTER TO MASTER_HOST='192.168.114.50',MASTER_USER='myslave',MASTER_PASSWORD='123456',MASTER_LOG_FILE='master-bin.00000x',MASTER_LOG_POS=xxxxx,MASTER_PORT=3306; #如master数据库端口不是3306要注意更改 START SLAVE; SHOW SLAVE STATUS\G; #如遇报错请尝试stop slave,然后reset slave,重新以上步骤
成功界面如下
3.3 主从复制测试
主库进行写入
从库查询是否同步
如从库也同步获取,即实验成功
四、用 MyCat 实现读写分离
4.1 MyCat 简要介绍
MyCat 是一个中间件(SQL 解析 + 转发),可以实现读写分离、分库分表及负载均衡。适合将客户端所有请求先发到 MyCat,由 MyCat 根据配置把写转到 Master,把读分发到从库。
4.2 MyCat 安装与配置步骤详解
4.2.1 下载与解压
从 MyCat 官网或 GitHub 发布页面下载最新稳定版本,解压到目标目录:
bash
wget http://dl.mycat.org.cn/2.0/install-template/mycat2-install-template-1.21.zip unzip mycat2-install-template-1.21.zip -d /usr/local/ mv /usr/local/mycat2-install-template-1.21 /usr/local/mycat
4.2.2 创建专用用户并授权
为安全起见,创建专门运行 MyCat 的用户:
bash
useradd -r -s /sbin/nologin mycat chown -R mycat:mycat /usr/local/mycat
4.2.3 目录结构说明
-
bin/
: 可执行文件和启动脚本(如mycat start|stop|status|console
) -
conf/
: 配置文件目录-
server.xml
: MyCat 服务器系统参数、用户权限配置 -
schema.xml
: 逻辑库、表、分片规则、数据节点配置 -
rule.xml
: 分片规则定义文件
-
-
lib/
: MyCat 运行所需的 Java 依赖库 -
logs/
: 日志文件目录(运行日志、SQL 日志等)
4.2.4 配置 Java 环境
MyCat 基于 Java 开发,需提前安装 JDK:
bash
tar -zxvf jdk-8u341-linux-x64.tar.gz -C /usr/local/ vim /etc/profile.d/java.sh
添加以下内容:
bash
export JAVA_HOME=/usr/local/jdk1.8.0_341 export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
使配置生效:
bash
source /etc/profile.d/java.sh java -version
4.2.5 配置 MyCat 环境变量
bash
vim /etc/profile.d/mycat.sh
添加内容:
bash
export MYCAT_HOME=/usr/local/mycat export PATH=$MYCAT_HOME/bin:$PATH
使配置生效:
bash
source /etc/profile.d/mycat.sh
4.2.6 配置主机名解析(可选)
在多节点环境中,建议配置 /etc/hosts
确保主机名解析:
text
192.168.114.50 master 192.168.114.251 slave1 192.168.114.252 slave2 192.168.114.180 mycat
4.3 MyCat 关键配置详解
4.3.1 配置 server.xml
主要配置系统参数和用户权限:
xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mycat:server SYSTEM "server.dtd"> <mycat:server xmlns:mycat="http://io.mycat/"><system><property name="defaultSqlParser">druidparser</property><property name="charset">utf8mb4</property><property name="useHandshakeV10">1</property></system><user name="mycat" defaultAccount="true"><property name="password">123456</property><property name="schemas">ha</property></user><user name="user"><property name="password">user</property><property name="schemas">ha</property><property name="readOnly">true</property></user> </mycat:server>
4.3.2 配置 schema.xml
这是最关键的配置文件,定义了逻辑库、数据节点和读写分离规则:
xml
<?xml version="1.0"?> <!DOCTYPE mycat:schema SYSTEM "schema.dtd"> <mycat:schema xmlns:mycat="http://io.mycat/"> <!-- 定义逻辑库 --><schema name="ha" checkSQLschema="false" sqlMaxLimit="100" dataNode="dn1"></schema> <!-- 定义数据节点 --><dataNode name="dn1" dataHost="dthost" database="ha" /><!-- 定义数据主机组 --><dataHost name="dthost" maxCon="500" minCon="10" balance="1"writeType="0" dbType="mysql" dbDriver="native" switchType="-1" slaveThreshold="100"><!-- 心跳检测语句 --><heartbeat>select user()</heartbeat><!-- 写节点(主库)配置 --><writeHost host="master" url="192.168.114.50:3306" user="mycat" password="123456"><!-- 读节点(从库)配置 --><readHost host="slave1" url="192.168.114.251:3306" user="mycat" password="123456"/><readHost host="slave2" url="192.168.114.252:3306" user="mycat" password="123456"/></writeHost></dataHost> </mycat:schema>
4.3.3 关键参数详解
balance 参数(负载均衡策略):
-
0
:不开启读写分离,所有读操作发送到当前可用的 writeHost -
1
:所有 readHost 与 stand by writeHost 参与 select 语句的负载均衡 -
2
:所有读操作随机在 writeHost、readhost 上分发 -
3
:所有读请求随机分发到 writeHost 对应的 readhost 执行
writeType 参数(写节点策略):
-
0
:所有写操作发送到配置的第一个 writeHost -
1
:所有写操作随机发送到配置的 writeHost(已废弃)
switchType 参数(切换策略):
-
-1
:不自动切换 -
1
:自动切换 -
2
:基于 MySQL 主从同步状态决定是否切换 -
3
:基于 MySQL Galera Cluster 切换机制
4.3.4 配置主/从库(如做完主从复制只需执行以下命令)
mysql> grant all privileges on *.* to 'mycat'@'%' identified by '123456';
mysql> flush privileges;
4.3.5 在MyCat端添加虚拟Ip用于测试
ip addr add 192.168.114.180/24 dev ens33
4.4 MyCat 启动与验证
4.4.1 启动 MyCat
bash
cd /usr/local/mycat/bin ./mycat start
如果成功显示,则表示Mycat成功启动
4.4.2 查看启动状态
bash
./mycat status
4.4.3 查看日志
bash
tail -f /usr/local/mycat/logs/wrapper.log
4.4.4 连接测试
bash
mysql -umycat -p123456 -h192.168.114.180 -P8066
4.4.5 测试读写分离
在主服务器上:
use test;
create table test123 (id int(10),name varchar(10),address varchar(20));
在两台从服务器上:
stop slave; #关闭同步
use test;
//在slave1上:
insert into test123 values('1','zs','this_is_slave1');
//在slave2上:
insert into test123 values('2','ls','this_is_slave2');
//在主服务器上:
insert into test123 values('3','ww','this_is_master');
//在客户端服务器上:
use test;
select * from test123; //客户端会分别向slave1和slave2读取数据,显示的只有在两个从服务器
上添加的数据,没有在主服务器上添加的数据
insert into test values('4','qq','this_is_client'); //只有主服务器上有此数据
//在两个从服务器上执行 start slave; 即可实现同步在主服务器上添加的数据
start slave;
实验效果
4.5 MyCat 配置常见易错点与解决方案
4.5.1 XML 格式错误
问题:配置文件格式不正确,如标签未闭合、属性值缺少引号等 解决:使用 XML 验证工具检查配置文件,确保所有标签正确闭合
4.5.2 数据库连接配置错误
问题:数据库地址、端口、用户名或密码配置错误 解决:仔细检查 schema.xml
中的连接信息,确保与实际情况一致
4.5.3 权限配置问题
问题:MyCat 用户没有足够的数据库权限
解决:确保数据库用户具有相应的 SELECT、INSERT、UPDATE、DELETE 权限
4.5.4 心跳检测配置不当
问题:心跳语句过于复杂或执行时间过长
解决:使用简单的心跳语句,如 select 1
或 select user()
4.5.5 负载均衡策略选择不当
问题:balance 参数配置不符合业务需求
解决:根据业务场景选择合适的负载均衡策略
4.5.6 连接池配置问题
问题:maxCon 或 minCon 配置不合理,导致连接池性能问题
解决:根据实际并发量调整连接池大小
4.5.7 字符集配置不一致
问题:MyCat、应用程序和数据库字符集不一致
解决:确保所有组件使用统一的字符集(推荐 utf8mb4)
4.5.8 防火墙和网络配置
问题:防火墙阻止了 MyCat 与数据库之间的通信
解决:检查防火墙设置,确保相关端口开放
4.6 MyCat 与事务/一致性
-
事务内:代理应该保证事务内的所有命令发往相同写节点(MyCat 默认行为应满足,但复杂场景需验证)。
-
读你写问题:MyCat 作为中间件,需配合"会话粘性"或回写路由策略以保证写后立即读的一致性(比如写后短期内把该会话读路由到主库)。
五、实验注意事项
-
时间同步:主从节点时间必须一致(
ntpdate
/chrony
),否则 binlog 时间戳与监控信息可能混乱。 -
端口与防火墙:确保
3306
(MySQL)、8066
(MyCat 默认)端口在内网可达;必要时开放或在防火墙上放行。 -
binlog 与 server-id:主库必须启用
log_bin
,并确保每台 MySQL 的server-id
唯一。 -
从库 read_only:将从库设置为
read_only=ON
,避免误操作写入。 -
复制用户权限:复制用户至少需
REPLICATION SLAVE
权限;若 MyCat 需要直接访问业务表,还需要相应的 DML 权限(按最小权限原则授予)。 -
测试读写分离一致性:写入主库后立即从 MyCat 发起 SELECT,观察是否命中从库(是否能读到新写入的数据);若读不到,说明需要采用"会话粘性"或路由策略。
-
监控 seconds_behind_master 的局限:
Seconds_Behind_Master
并非绝对准确(值可能为 NULL 或被"卡住"),应结合Relay_Log_Space
、Slave_IO_Running
、Slave_SQL_Running
及应用层指标进行判断。 -
日志与排错:MyCat 的
logs/wrapper.log
,MySQL 的error.log
都是故障排查的第一手资料。 -
DDL 与 binlog:执行DDL 时要小心(会阻塞复制/造成从库短暂不一致);大型变更建议使用在线 DDL 工具或在低峰进行。
-
备份策略:定期做逻辑(
mysqldump
)或物理(Percona Xtrabackup)备份,并保留 binlog 以便增量恢复。
六、常见故障与排查命令(快捷参考)
-
查看主库 binlog 状态:
text
SHOW MASTER STATUS\G;
-
查看从库复制状态:
text
SHOW SLAVE STATUS\G; # 关键字段:Slave_IO_Running, Slave_SQL_Running, Seconds_Behind_Master, Last_IO_Error, Last_SQL_Error
-
如果 I/O 线程卡住(connecting),看
Last_IO_Error
,常见原因:网络/认证/host 白名单问题。 -
如果 SQL 线程报错导致停止(例如语法/数据冲突),可先
STOP SLAVE; SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; START SLAVE;
(仅在确认可跳过某单条事务时使用,谨慎)。 -
重新定位复制位置(当 binlog 不匹配时):
-
在 master 执行
FLUSH LOGS; SHOW MASTER STATUS\G;
-
在 slave 执行
STOP SLAVE; CHANGE MASTER TO MASTER_LOG_FILE='xxx', MASTER_LOG_POS=yyy; START SLAVE;
-
七、监控、备份、告警与安全
7.1 监控 & 告警
-
重点监控:
Slave_IO_Running
、Slave_SQL_Running
、Seconds_Behind_Master
、binlog 使用量、磁盘 IO、InnoDB buffer pool 命中率、慢查询。 -
告警场景:复制中断、落后持续超阈值、磁盘占满、异常高的慢查询数。
-
常用工具:Prometheus + mysqld_exporter、Percona Monitoring and Management (PMM)、Zabbix、Nagios。
7.2 备份与恢复
-
冷备/逻辑备份:
mysqldump
(适合小库或导出结构)。 -
热备/物理备份:Percona XtraBackup 支持在线热备,恢复时配合 binlog 执行增量恢复。
-
定期做恢复演练(restore drill),确认备份有效性。
7.3 安全
-
复制用户的来源 IP 最小化(如只允许
192.168.114.%
)。 -
使用 TLS/SSL 加密复制链路(避免明文在网络传输)。
-
从库开启
read_only
;尽量不在从库上进行临时写操作。 -
严格控制 MyCat/数据库用户权限,记录审计日志。
八、性能与可靠性调优建议
-
binlog_format=ROW
(准确性)或MIXED
(兼顾);注意 ROW 的 binlog 更大。 -
sync_binlog=1
与innodb_flush_log_at_trx_commit=1
提升耐久性,但会影响写吞吐,按业务需求权衡。 -
innodb_buffer_pool_size
预留 ~70–80% 内存给 InnoDB(数据库专用机器)。 -
在从库上开启
slave_parallel_workers
(并行应用)以利用多核 CPU(注意并发安全条件)。 -
max_connections
、table_open_cache
等参数根据并发做调整。 -
使用 SSD 提升 IO 性能、降低复制延迟。
九、快速实验流程
-
在 Master(192.168.114.50)开启 binlog,创建复制用户。
-
在 Slave1/Slave2(192.168.114.251 / .252)设置 server-id、relay-log,执行
CHANGE MASTER TO
并START SLAVE
。 -
部署 MyCat(192.168.114.180),配置
schema.xml
把主从加入读写路由。 -
客户端(192.168.114.253)通过 MyCat 端口(8066)访问数据库,验证:写走主库、读由从库分担。
-
做断网 / 单节点宕机容错测试、读写一致性(写后立即读),并根据结果调整路由策略或使用会话粘性方案。
十、结语与后续建议
-
本文把复制/读写分离的原理和实战结合起来,并用 MyCat 作为示例进行代理层实现。
-
在实际生产中,必须在非生产环境充分验证:事务行为、读写一致性策略、故障切换流程与备份恢复流程。
-
随着业务复杂度提升,可逐步引入更高级的架构方案,如基于 MHA 或 Orchestrator 的自动故障转移、基于 ProxySQL 的更精细路由控制等。
-
定期回顾和优化数据库架构,确保其能够支撑业务的持续增长和技术演进。
附录:MyCat 常用管理命令
bash
# 启动 MyCat /usr/local/mycat/bin/mycat start # 停止 MyCat /usr/local/mycat/bin/mycat stop # 查看状态 /usr/local/mycat/bin/mycat status # 控制台运行(前台模式,查看详细日志) /usr/local/mycat/bin/mycat console # 重启 /usr/local/mycat/bin/mycat restart
通过以上详细的配置步骤和原理解析,相信您已经能够熟练掌握使用 MyCat 实现 MySQL 主从复制和读写分离的技术方案。在实际部署过程中,请根据具体业务需求和环境特点进行适当调整和优化。