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. 生产环境需开启主从监控、心跳检测、故障自动切换
相关推荐
-ONLY-¥3 小时前
MySQL主从复制与读写分离实战
adb
独隅3 小时前
MacOS 系统下 ADB (Android Debug Bridge) 全面安装与配置指南
android·macos·adb
刘晨鑫14 小时前
MySQL主从复制与读写分离
数据库·mysql·adb
炸炸鱼.1 天前
MySQL 全量、增量备份与恢复(极简易懂版)
android·adb
独隅1 天前
Linux 系统下 ADB 环境 的详细安装步骤和基础设置指南
linux·运维·adb
2301_805348971 天前
MySQL源码编译部署主从及MHA高可用集群实战
adb
Carino_U1 天前
全面理解mysql架构
mysql·adb·架构
w-白兰地1 天前
配置Unity中的ADB环境变量
unity·adb·游戏引擎