前言
在互联网高并发业务场景下,单节点 MySQL 数据库面临并发瓶颈、单点故障、读写性能不足 三大核心问题。MySQL 主从复制实现数据实时同步与灾备,读写分离将写请求路由主库、读请求分摊从库,是企业级数据库架构的标配方案。
本文基于OpenEuler 24.03 系统,完整搭建1 主 2 从 MySQL 集群 ,并通过MyCat2 中间件实现透明化读写分离,包含原理讲解、环境规划、分步配置、验证测试、故障排查全流程,可直接用于生产部署与学习实操。
一、核心原理精讲
1.1 MySQL 主从复制原理
MySQL 主从复制是基于 ** 二进制日志(Binlog)** 的异步数据同步机制,是读写分离的基础。
1.1.1 复制类型
表格
| 复制类型 | 核心逻辑 | 优点 | 缺点 | 生产建议 |
|---|---|---|---|---|
| 基于语句复制(默认) | 主库执行 SQL,从库重放相同语句 | 日志体积小、效率高 | 部分函数 / 存储过程复制不精准 | 不推荐单独使用 |
| 基于行复制 | 同步数据行变更内容,不重放 SQL | 复制精准、无歧义 | 日志体积大、网络开销高 | 数据一致性要求高场景使用 |
| 混合模式复制 | 优先语句复制,不精准时自动切换行复制 | 兼顾效率与精准 | 无明显缺点 | 生产环境首选 |
1.1.2 复制工作流程
- 主库:事务提交前,将数据变更写入二进制日志(Binlog);
- 从库 I/O 线程 :建立主库连接,拉取 Binlog 并写入中继日志(Relay Log);
- 从库 SQL 线程:读取中继日志,重放日志事件,保持从库与主库数据一致。
关键限制:从库复制为串行执行,主库并行更新在从库无法并行,可能存在主从延迟。
1.2 读写分离原理
读写分离核心规则:主库负责写,从库负责读。
- 写操作(INSERT/UPDATE/DELETE/DDL):仅路由到主库;
- 读操作(SELECT):路由到从库,分摊主库读压力;
- 主从复制保证数据最终一致性。
1.2.1 读写分离实现方式
表格
| 实现方式 | 代表方案 | 优点 | 缺点 |
|---|---|---|---|
| 代码层实现 | 业务代码 SQL 路由 | 性能好、无额外组件 | 开发侵入性强、维护复杂 |
| 中间件代理 | MySQL-Proxy、Amoeba、MyCat | 对应用透明、运维友好 | 增加部署组件、需维护 |
MyCat2:开源分布式数据库中间件,兼容 MySQL 协议,支持读写分离、分库分表、负载均衡,是生产环境主流选择。
二、实验环境规划
2.1 服务器拓扑
本次使用5 台 OpenEuler 24.03 服务器,搭建标准 1 主 2 从 + MyCat2 代理架构。
表格
| 主机角色 | 操作系统 | IP 地址 | 部署服务 | 核心作用 |
|---|---|---|---|---|
| Master | OpenEuler 24.03 | 192.168.10.101 | MySQL 8.0.36 | 主库,负责所有写操作 |
| Slave1 | OpenEuler 24.03 | 192.168.10.102 | MySQL 8.0.36 | 从库,负责读请求 |
| Slave2 | OpenEuler 24.03 | 192.168.10.103 | MySQL 8.0.36 | 从库,负责读请求 |
| MyCat | OpenEuler 24.03 | 192.168.10.104 | MyCat2 | 读写分离代理、负载均衡 |
| 客户端 | OpenEuler 24.03 | 192.168.10.105 | MySQL 客户端 | 业务测试、验证读写分离 |
2.2 实验目标
- 完成 MySQL 8.0.36 二进制安装;
- 实现 1 主 2 从主从复制;
- 部署 MyCat2 并配置读写分离;
- 验证写走主库、读轮询从库;
- 掌握故障排查与状态验证方法。
三、前置准备(所有节点执行)
3.1 时间同步
主从复制对时间敏感,必须保证所有节点时间一致。
yum -y install ntpdate
ntpdate ntp1.aliyun.com
3.2 关闭防火墙与 SELinux
生产环境可开放指定端口,实验环境直接关闭。
systemctl stop firewalld
systemctl disable firewalld
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0
3.3 安装基础依赖
dnf -y install gcc vim wget net-tools lrzsz tar libaio numactl openssl ncurses-compat-libs
3.4 创建 MySQL 专用用户
useradd -M -s /sbin/nologin mysql
四、MySQL 8.0.36 二进制安装(主从节点通用)
4.1 解压与目录配置
tar xJf mysql-8.0.36-linux-glibc2.28-x86_64.tar.xz
mv mysql-8.0.36-linux-glibc2.28-x86_64 /usr/local/mysql
mkdir /usr/local/mysql/data
chown -R mysql:mysql /usr/local/mysql/data
4.2 初始化 MySQL
cd /usr/local/mysql/bin
./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data
重要:记录控制台输出的临时密码,用于首次登录。
4.3 配置 my.cnf
[client]
socket=/usr/local/mysql/data/mysql.sock
[mysqld]
socket=/usr/local/mysql/data/mysql.sock
bind-address = 0.0.0.0
port = 3306
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
max_connections=2048
default-storage-engine=INNODB
skip-name-resolve
character-set-server=utf8
max_allowed_packet=16M
4.4 配置环境变量
bash
运行
echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
source /etc/profile
4.5 配置 systemd 服务
bash
运行
cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysqld
chmod +x /etc/rc.d/init.d/mysqld
vim /lib/systemd/system/mysqld.service
写入以下内容:
ini
[Unit]
Description=mysqld
After=network.target
[Service]
Type=forking
ExecStart=/etc/rc.d/init.d/mysqld start
ExecReload=/etc/rc.d/init.d/mysqld restart
ExecStop=/etc/rc.d/init.d/mysqld stop
PrivateTmp=true
[Install]
WantedBy=multi-user.target
启动并设置开机自启:
bash
运行
systemctl daemon-reload
systemctl enable mysqld
systemctl start mysqld
4.6 修改 root 密码
bash
运行
mysqladmin -u root password 'pwd123'
五、MySQL 主从复制配置
5.1 主库(Master)配置
5.1.1 修改 my.cnf 开启 Binlog
ini
server-id=1 # 集群内唯一,主库设为1
log-bin=/usr/local/mysql/data/mysql-bin # 开启Binlog
binlog_format = MIXED # 混合复制模式,生产首选
5.1.2 重启 MySQL 服务
bash
运行
systemctl restart mysqld
5.1.3 创建复制授权账号
MySQL 8.0 需修改认证插件为mysql_native_password,保证兼容性。
sql
mysql -u root -p
# 创建复制账号
CREATE USER 'myslave'@'%' IDENTIFIED BY '123456';
# 授予复制权限
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'%';
# 修改认证插件
ALTER USER 'myslave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;
5.1.4 查看主库状态
sql
show master status;
记录File (日志文件名)和Position(偏移量),从库配置需使用。
5.2 从库(Slave1/Slave2)配置
5.2.1 修改 my.cnf
- Slave1:
server-id=2 - Slave2:
server-id=3
注意:server-id 必须唯一,不能与主库 / 其他从库重复。
bash
运行
systemctl restart mysqld
5.2.2 配置主从同步
sql
mysql -u root -p
change master to
master_host='192.168.10.101', # 主库IP
master_user='myslave', # 复制账号
master_password='123456', # 复制密码
master_log_file='mysql-bin.000001',# 主库File值
master_log_pos=157; # 主库Position值
# 启动同步
start slave;
5.2.3 验证从库状态
sql
show slave status\G
必须满足以下两个参数为 YES,代表同步正常:
- Slave_IO_Running: Yes
- Slave_SQL_Running: Yes
5.3 主从复制验证
- 主库创建测试库:
create database db_test; - 从库执行:
show databases; - 从库能看到
db_test,代表主从复制配置成功。
六、MyCat2 部署与读写分离配置
6.1 MyCat2 依赖安装(JDK8)
MyCat2 基于 Java 开发,必须安装 JDK8。
bash
运行
dnf install jdk-8u171-linux-x64.rpm
6.2 MyCat2 安装部署
bash
运行
# 解压安装包
unzip mycat2-install-template-1.20.zip -d /usr/local/
mv /usr/local/mycat2-install-template-1.20 /usr/local/mycat
# 配置环境变量
echo 'export PATH=$PATH:/usr/local/mycat/bin' >> /etc/profile
source /etc/profile
# 复制核心依赖包
cp mycat2-1.21-release-jar-with-dependencies.jar /usr/local/mycat/lib
cp mysql-connector-java-8.0.18.jar /usr/local/mycat/lib
# 添加执行权限
chmod -R +x /usr/local/mycat/bin
# 验证安装
mycat -h
6.3 主库创建 MyCat 专用账号
sql
create user 'mycat'@'%' identified by 'pwd123';
grant all on *.* to 'mycat'@'%';
ALTER USER 'mycat'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123';
flush privileges;
6.4 MyCat2 数据源配置
MyCat2 默认端口8066 ,登录账号:root/123456。
bash
运行
mysql -uroot -p123456 -P8066 -h192.168.10.104
6.4.1 添加主库数据源(WRITE 类型)
sql
/*+ mycat:createDataSource{
"name":"master",
"url":"jdbc:mysql://192.168.10.101:3306/?useSSL=false&characterEncoding=UTF-8",
"instanceType":"WRITE",
"user":"mycat",
"password":"pwd123"
} */;
6.4.2 添加从库数据源(READ 类型)
sql
-- slave1
/*+ mycat:createDataSource{
"name":"slave1",
"url":"jdbc:mysql://192.168.10.102:3306/?useSSL=false&characterEncoding=UTF-8",
"instanceType":"READ",
"user":"mycat",
"password":"pwd123"
} */;
-- slave2
/*+ mycat:createDataSource{
"name":"slave2",
"url":"jdbc:mysql://192.168.10.103:3306/?useSSL=false&characterEncoding=UTF-8",
"instanceType":"READ",
"user":"mycat",
"password":"pwd123"
} */;
6.4.3 查看数据源配置
sql
/*+ mycat:showDataSources{} */\G
6.5 创建 MyCat 读写分离集群
sql
/*! mycat:createCluster{
"name":"cls01",
"masters":["master"], # 主库节点
"replicas":["slave1","slave2"] # 从库节点
} */;
6.6 配置轮询负载均衡
修改/usr/local/mycat/conf/server.json:
json
"loadBalance":{
"defaultLoadBalance":"BalanceRoundRobin"
}
重启 MyCat 使配置生效:
bash
运行
mycat restart
七、读写分离功能验证
7.1 测试数据准备
- 登录 MyCat 创建测试库表:
sql
create database test;
use test;
create table zang(id int(10),name varchar(10),address varchar(20));
- 停止从库同步(隔离数据,方便验证):
sql
stop slave;
- 分别插入标识数据:
- 主库:
insert into zang values('1','zang','this_is_master'); - Slave1:
insert into zang values('2','zang','this_is_slave1'); - Slave2:
insert into zang values('3','zang','this_is_slave2');
7.2 读请求验证(从库轮询)
通过 MyCat 多次执行查询:
sql
select * from test.zang;
- 第一次查询:返回 slave1 数据
- 第二次查询:返回 slave2 数据
- 第三次查询:返回 slave1 数据证明读请求轮询分摊到从库。
7.3 写请求验证(主库写入)
通过 MyCat 执行写入操作:
sql
insert into zang values('4','zhang','write_test');
- 从库查询:无此数据
- 主库查询:可查到该数据 证明写请求仅路由到主库,读写分离配置完全生效。
八、常见故障排查
8.1 主从复制异常
表格
| 异常现象 | 原因 | 解决方案 |
|---|---|---|
| Slave_IO_Running=No | 网络不通、账号密码错误、防火墙拦截 | 检查 IP / 账号 / 密码,关闭防火墙 |
| Slave_SQL_Running=No | 主从数据不一致、SQL 执行报错 | stop slave; set global sql_slave_skip_counter=1; start slave; |
| 主从延迟高 | 从库性能不足、大事务、网络慢 | 升级从库配置、拆分大事务、优化网络 |
8.2 MyCat 连接异常
- 8066 端口未监听:JDK 未安装 / MyCat 启动失败,查看
wrapper.log日志; - 认证失败:MySQL 8 未修改认证插件为
mysql_native_password; - 数据源异常:检查 IP、端口、账号、密码配置。
8.3 读写分离不生效
- 集群未配置
readBalanceType=BALANCE_ALL_READ; - 从库
instanceType未设为READ; - 负载均衡策略未配置轮询。
九、总结
本文完整实现了MySQL 主从复制 + MyCat2 读写分离的生产级架构,核心成果:
- 完成 MySQL 8.0.36 二进制安装与 1 主 2 从复制;
- 实现 MyCat2 读写分离、从库轮询负载均衡;
- 验证写主库、读从库的核心架构逻辑;
- 提供完整故障排查方案,可直接落地生产。
该架构有效解决 MySQL 高并发读写瓶颈,提升数据库可用性、扩展性、并发能力,是互联网企业数据库架构的基础方案。