MySQL 主从复制与读写分离

本文基于 MySQL 8.0 + openEuler 24.03,用最简步骤实现主从复制 + MyCat2 读写分离,包含全套可复制代码与关键知识点。


一、核心原理(必懂)

1. 主从复制

  • 作用:主库写、从库读,数据实时同步,分担压力、容灾备份。
  • 流程:
    1. 主库写入 binlog 二进制日志
    2. 从库 IO 线程拉取 binlog 到 relay log
    3. 从库 SQL 线程重放日志,保持数据一致
  • 复制类型:
    • STATEMENT:基于 SQL 语句(默认,高效)
    • ROW:基于行数据变更(精准)
    • MIXED:混合模式(自动切换)

2. 读写分离

  • 规则:写 → 主库,读 → 从库
  • 实现方式:
    1. 代码层:业务代码判断 SQL 路由
    2. 中间件:MyCat、Amoeba、MySQL-Proxy(本文用 MyCat2)

二、环境准备(5 台服务器)

表格

角色 IP 应用
Master 192.168.10.101 MySQL 8.0
Slave1 192.168.10.102 MySQL 8.0
Slave2 192.168.10.103 MySQL 8.0
MyCat2 192.168.10.104 MyCat2 + JDK8
Client 192.168.10.105 MySQL 客户端

2. 环境准备(所有节点执行)

bash

运行

复制代码
# 时间同步
yum -y install ntpdate
ntpdate ntp1.aliyun.com

# 关闭防火墙与SELinux
systemctl stop firewalld
systemctl disable firewalld
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
setenforce 0

3. MySQL 二进制安装(主 / 从都执行)

bash

运行

复制代码
# 安装依赖
dnf -y install gcc vim wget net-tools lrzsz tar libaio numactl openssl ncurses-compat-libs

# 创建mysql用户
useradd -M -s /sbin/nologin mysql

# 解压安装
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

# 初始化(记录临时密码)
cd /usr/local/mysql/bin
./mysqld --initialize --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/data

4. MySQL 配置文件(/etc/my.cnf)

ini

复制代码
[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

5. 配置系统服务与环境变量

bash

运行

复制代码
# 环境变量
echo "export PATH=$PATH:/usr/local/mysql/bin" >> /etc/profile
source /etc/profile

# 配置systemd
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

# 修改root密码
mysqladmin -u root password 'pwd123'

6. 主库(Master)配置(192.168.10.101)

bash

运行

复制代码
# 修改my.cnf
vim /etc/my.cnf

添加:

ini

复制代码
server-id=1
log-bin=/usr/local/mysql/data/mysql-bin
binlog_format = MIXED

bash

运行

复制代码
systemctl restart mysqld

# 登录MySQL授权从库
mysql -u root -p

sql

复制代码
CREATE USER 'myslave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'myslave'@'%';
ALTER USER 'myslave'@'%' IDENTIFIED WITH mysql_native_password BY '123456';
FLUSH PRIVILEGES;

# 查看主库状态(记录File和Position)
show master status;

7. 从库(Slave1/Slave2)配置

Slave1(192.168.10.102)

bash

运行

复制代码
vim /etc/my.cnf

ini

复制代码
server-id=2

bash

运行

复制代码
systemctl restart mysqld

Slave2(192.168.10.103)

bash

运行

复制代码
vim /etc/my.cnf

ini

复制代码
server-id=3

bash

运行

复制代码
systemctl restart mysqld

两台从库执行同步命令

sql

复制代码
mysql -uroot -p

change master to 
master_host='192.168.10.101',
master_user='myslave',
master_password='123456',
master_log_file='mysql-bin.000001',
master_log_pos=157;

start slave;

# 检查状态(两个必须为YES)
show slave status\G

关键项:Slave_IO_Running: YesSlave_SQL_Running: Yes

8. 主从复制验证

sql

复制代码
# 主库创建库
create database db_test;

# 从库查看
show databases;

三、MySQL 读写分离(Mycat2)

1. 核心原理(补充知识点)

  1. 读写分离两种实现
    • 代码层:代码判断 SQL 路由,性能好,改造成本高
    • 代理层:Mycat、Amoeba、MySQL-Proxy,对应用透明
  2. Mycat2 优势
    • 兼容 MySQL 协议
    • 支持读写分离、分库分表
    • 配置简单,支持 SQL 命令配置

2. Mycat2 安装(192.168.10.104)

bash

运行

复制代码
# 安装JDK
dnf install jdk-8u171-linux-x64.rpm -y

# 解压Mycat2
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 mysql-connector-java-8.0.18.jar /usr/local/mycat/lib
cp mycat2-1.21-release-jar-with-dependencies.jar /usr/local/mycat/lib

# 赋权
chmod -R +x /usr/local/mycat/bin

# 验证安装
mycat -h

3. 主库创建 Mycat 账号

sql

复制代码
mysql -uroot -p

create user 'mycat'@'%' identified by 'pwd123';
grant all on *.* to 'mycat'@'%';
ALTER USER 'mycat'@'%' IDENTIFIED WITH mysql_native_password BY 'pwd123';
flush privileges;

4. Mycat2 配置读写分离

bash

运行

复制代码
# 启动Mycat
mycat start

# 连接Mycat(端口8066)
mysql -uroot -p123456 -P8066 -h192.168.10.104
(1)添加数据源

sql

复制代码
-- 主库(写)
/*+ mycat:createDataSource{ 
"name":"master",
"url":"jdbc:mysql://192.168.10.101:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",
"instanceType":"WRITE",
"user":"mycat",
"password":"pwd123"
} */;

-- 从库1(读)
/*+ mycat:createDataSource{ 
"name":"slave1",
"url":"jdbc:mysql://192.168.10.102:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",
"instanceType":"READ",
"user":"mycat",
"password":"pwd123"
} */;

-- 从库2(读)
/*+ mycat:createDataSource{ 
"name":"slave2",
"url":"jdbc:mysql://192.168.10.103:3306/?useSSL=false&characterEncoding=UTF-8&useJDBCCompliantTimezoneShift=true",
"instanceType":"READ",
"user":"mycat",
"password":"pwd123"
} */;

-- 查看数据源
/*+ mycat:showDataSources{} */\G
(2)创建集群

sql

复制代码
/*! mycat:createCluster{
"name":"cls01",
"masters":["master"],
"replicas":["slave1","slave2"]
} */;
(3)修改集群负载均衡(轮询)

bash

运行

复制代码
vim /usr/local/mycat/conf/clusters/cls01.cluster.json

json

复制代码
"readBalanceType":"BALANCE_ALL_READ",
"balance": 1

bash

运行

复制代码
vim /usr/local/mycat/conf/server.json

json

复制代码
"loadBalance":{
"defaultLoadBalance":"BalanceRoundRobin"
}

bash

运行

复制代码
mycat restart

5. 读写分离验证

sql

复制代码
# Mycat创建库表
create database test;
use test;
create table zang(id int(10),name varchar(10),address varchar(20));

bash

运行

复制代码
# 从库停止同步
mysql -uroot -p -h192.168.10.102
stop slave;

mysql -uroot -p -h192.168.10.103
stop slave;

sql

复制代码
# 主库插入
insert into test.zang values('1','zang','this_is_master');

# 从库1插入
insert into test.zang values('2','zang','this_is_slave1');

# 从库2插入
insert into test.zang values('3','zang','this_is_slave2');

sql

复制代码
# Mycat查询(轮询读从库)
select * from test.zang;

# Mycat写入(只写主库)
insert into zang values('4','zhang','write_test');

六、补充知识点(面试 / 运维常用)

  1. server-id 必须唯一,同一集群内不能重复。
  2. MySQL 8.0 默认认证插件为 caching_sha2_password,需改为 mysql_native_password 兼容中间件。
  3. 主从延迟:从库单线程重放,高并发下会延迟,可用并行复制优化。
  4. MyCat 端口:
    • 8066:数据端口(业务访问)
    • 9066:管理端口
  5. 读写分离策略:
    • BALANCE_ALL_READ:所有读走从库
    • BalanceRoundRobin:从库轮询负载
  6. 常见异常:
    • Slave_IO 异常:网络 / 账号 / 防火墙问题
    • Slave_SQL 异常:从库数据冲突、主键重复

七、整体总结

  1. 先主从复制,再读写分离,顺序不可颠倒。
  2. 主库负责写,从库负责读,大幅降低主库压力。
  3. MyCat 作为中间件,对应用透明,无需修改业务代码。
  4. 生产环境需开启主从监控、心跳检测、故障自动切换
相关推荐
通往曙光的路上2 小时前
mysql2
android·adb
Riu_Peter4 小时前
【技术】Docker 部署 MySQL
mysql·adb·docker
老码观察1 天前
K8s集群断电后MySQL恢复实录:从InnoDB崩溃到数据完整迁移
mysql·adb·kubernetes
黄俊懿4 天前
复合索引设计指南:最左前缀 & 字段排座次
数据库·sql·mysql·adb·性能优化·dba·db
aaa最北边4 天前
MySQL-锁
数据库·mysql·adb
fTiN CAPA5 天前
Linux系统离线部署MySQL详细教程(带每步骤图文教程)
linux·mysql·adb
hjc_0420435 天前
xtrabackup来备份恢复数据
运维·adb
小江的记录本5 天前
【MySQL】《MySQL基础架构 面试核心考点问答清单》
前端·数据库·后端·sql·mysql·adb·面试
秋95 天前
java中对操作mysql8.0.46与MySQL9.7.0有什么区别,并举例说明
android·java·adb
街灯L6 天前
【ADB】使用ADB工具箱卸载安卓系统软件
android·adb