mysql实现主从复制的详细步骤(非docker部署)

一、背景介绍:为什么需要 MySQL 主从复制?

在实际生产环境中,单台 MySQL 服务器存在明显的风险和性能瓶颈:

  • 单点故障:一旦服务器宕机,业务将完全中断;
  • 性能瓶颈:读写请求全部集中在一台服务器,高并发场景下响应缓慢;
  • 数据安全:单节点存储数据,硬件故障可能导致数据丢失。

MySQL 主从复制(Master-Slave Replication)是解决上述问题的经典方案:

  • 主库(Master):负责处理所有写操作(增删改),是数据的 “源头”;
  • 从库(Slave):通过复制主库的二进制日志(binlog)同步数据,主要处理读操作(查询);
  • 核心价值:实现读写分离、数据备份、故障转移,提升系统可用性和性能。

本文基于 CentOS 7 系统和 MySQL 5.7 版本,从零开始拆解主从复制的搭建流程,包含环境准备、安装配置、同步测试和问题排查,适合运维工程师和后端开发人员学习实践。

二、核心关键词解释

  • 二进制日志(binlog):主库记录所有数据变更操作的日志文件,是主从复制的 “数据源”;
  • 中继日志(relay log):从库接收主库的 binlog 后,先写入中继日志,再逐步执行,避免直接执行 binlog 导致的性能问题;
  • server-id:主从服务器的唯一标识(必须不同),用于区分复制拓扑中的节点;
  • 复制用户:主库中专门用于从库连接并获取 binlog 的用户,需授予REPLICATION SLAVE权限;
  • GTID(全局事务标识符):MySQL 5.6 + 引入的特性,通过全局唯一 ID 标识事务,简化复制配置(本文使用传统的日志文件 + 位置方式)(暂时与本文无关)。

三、环境准备

1. 基础要求

  • 两台 CentOS 7 服务器(分别作为主库、从库):硬件配置建议 2 核 4G 以上,确保网络互通;
  • 安装相同版本 MySQL(推荐 5.7.x):版本不一致可能导致 binlog 解析错误,本文以 5.7.44 为例;
  • 关闭防火墙及 SELinux:避免端口拦截或权限限制(生产环境可按需配置规则,而非直接关闭)。

2. 网络与主机配置

主服务器操作(IP:192.168.238.134)

bash

# 设置主机名(便于识别节点角色,替换为实际域名/名称)
hostnamectl set-hostname master.yourdomain.com

# 配置静态IP(编辑网卡文件,CentOS 7默认网卡为ens33,可通过ip addr查看)
vim /etc/sysconfig/network-scripts/ifcfg-ens33

# 网卡配置内容(根据实际网络环境修改):
BOOTPROTO=static       # 静态IP模式(避免DHCP分配导致IP变化)
IPADDR=192.168.238.134 # 主服务器固定IP
PREFIX=24              # 子网掩码前缀(24对应255.255.255.0)
GATEWAY=192.168.238.2  # 网关地址(与路由器/交换机配置一致)
DNS1=114.114.114.114   # DNS服务器(国内常用114或阿里云DNS)
ONBOOT=yes             # 开机自动激活网卡

# 重启网络服务使配置生效
systemctl restart network
从服务器操作(IP:192.168.238.133)

bash

# 设置主机名(区分主从节点)
hostnamectl set-hostname slave.yourdomain.com

# 配置静态IP(网卡名称需与主库一致)
vim /etc/sysconfig/network-scripts/ifcfg-ens33

# 网卡配置内容(网关/DNS与主库保持一致):
BOOTPROTO=static
IPADDR=192.168.238.133 # 从服务器固定IP
PREFIX=24
GATEWAY=192.168.238.2  # 与主库同一网关
DNS1=114.114.114.114
ONBOOT=yes

# 重启网络
systemctl restart network

3. 基础环境配置(两台服务器均执行)

bash

# 关闭NetworkManager(避免与network服务冲突,按需选择)
systemctl stop NetworkManager && systemctl disable NetworkManager

# 配置hosts文件(绑定IP与主机名,避免DNS解析问题)
vim /etc/hosts
# 添加内容(替换为实际IP和主机名):
192.168.238.134 master.yourdomain.com
192.168.238.133 slave.yourdomain.com

# 关闭防火墙和SELinux(临时+永久)
systemctl stop firewalld && systemctl disable firewalld  # 关闭防火墙
setenforce 0                                             # 临时关闭SELinux
sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config  # 永久关闭SELinux(需重启生效)

# 时间同步(确保主从服务器时间一致,避免复制延迟判断错误)
yum install -y ntp                  # 安装ntp工具
ntpdate time1.aliyun.com            # 同步阿里云NTP服务器时间(生产环境建议用内部NTP)

# 检查3306端口是否被占用(避免端口冲突)
# 方法1:使用netstat(需安装net-tools)
yum install -y net-tools
netstat -tulpn | grep 3306

# 方法2:使用lsof(需安装lsof)
yum install -y lsof
lsof -i :3306

# 若端口被占用,终止占用进程(替换<PID>为实际进程ID)
# kill -9 <PID>

四、安装 MySQL 5.7(主库与从库分别操作)

📌 重要原则

  • 主从服务器必须使用完全相同的 MySQL 版本(本文为 5.7.44)
  • 仅通过官方 YUM 仓库 + RPM 安装,严禁混用源码编译版本
  • 若系统曾安装过其他版本 MySQL(如 /usr/local/mysql),必须彻底清理

步骤 1:【主库 & 从库】彻底清理旧版 MySQL(关键!)

⚠️ 若跳过此步,极易因残留文件导致服务启动失败或端口冲突!

# 1. 停止所有 MySQL 进程
sudo systemctl stop mysqld 2>/dev/null
sudo pkill -f "/usr/local/mysql" 2>/dev/null

# 2. 卸载已安装的 MySQL RPM 包(如有)
sudo rpm -qa | grep mysql | xargs sudo rpm -e --nodeps 2>/dev/null

# 3. 删除源码安装残留(重点!)
sudo rm -rf /usr/local/mysql
sudo rm -f /usr/bin/mysql*
sudo rm -f /etc/my.cnf
sudo rm -f /etc/init.d/mysqld

# 4. 清理数据与日志目录
sudo rm -rf /var/lib/mysql
sudo rm -rf /var/log/mysqld.log

# 5. 清理用户(可选,避免权限混乱)
sudo userdel -r mysql 2>/dev/null

💡 执行后验证:which mysql 应返回空;ps aux | grep mysqld 应无进程。


步骤 2:【主库 & 从库】导入 MySQL 官方 GPG 公钥

🔐 GPG 密钥用于验证 RPM 包真实性,防止安装被篡改的软件包。

# 下载并导入两个官方 GPG 密钥(覆盖新旧签名)
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql
sudo rpm --import https://repo.mysql.com/RPM-GPG-KEY-mysql-2023

# 验证是否导入成功
rpm -q gpg-pubkey --qf '%{NAME}-%{VERSION}-%{RELEASE}\t%{SUMMARY}\n' | grep -i mysql

✅ 预期输出(示例):

1gpg-pubkey-3a79bd29-63f48c7b    gpg(MySQL Release Engineering <mysql-build@oss.oracle.com>)
2gpg-pubkey-859be8d7-63f48c7b    gpg(MySQL Package signing key (www.mysql.com) <build@mysql.com>)

❗ 若未导入,后续 yum install 可能报错:GPG check FAILEDMISSING KEYS


步骤 3:【主库 & 从库】配置 MySQL 5.7 YUM 仓库

# 创建仓库文件
sudo tee /etc/yum.repos.d/mysql57-community.repo <<'EOF'
[mysql57-community]
name=MySQL 5.7 Community Server
baseurl=https://repo.mysql.com/yum/mysql-5.7-community/el/7/$basearch/
enabled=1
gpgcheck=1
gpgkey=https://repo.mysql.com/RPM-GPG-KEY-mysql-2023
EOF

# 清理并重建 yum 缓存
sudo yum clean all
sudo yum makecache

✅ 验证仓库可用性:

yum repolist enabled | grep mysql
# 应看到 mysql57-community

步骤 4:【主库 & 从库】安装 MySQL 5.7 社区版

# 安装完整套件(包含 server, client, common, libs 等)
sudo yum install -y mysql-community-server

⏳ 安装过程会自动下载以下关键组件:

  • mysql-community-common
  • mysql-community-libs
  • mysql-community-client
  • mysql-community-server

💡 特别注意

  • 不要单独安装 .rpm 文件(除非网络受限且能保证依赖完整)
  • 必须通过 yum install 自动解决依赖,否则可能缺失 mysql 客户端命令

步骤 5:【主库 & 从库】验证安装结果

# 1. 检查服务状态(此时应未启动)
sudo systemctl status mysqld  # 应显示 "inactive"

# 2. 检查关键文件是否存在
ls -l /usr/sbin/mysqld          # 服务端二进制
ls -l /usr/bin/mysql            # 客户端命令(必须存在!)
ls -l /usr/lib/systemd/system/mysqld.service

# 3. 检查预启动脚本(避免 status=203 错误)
ls -l /usr/bin/mysqld_pre_systemd
file /usr/bin/mysqld_pre_systemd  # 应为 shell script

❌ 若 /usr/bin/mysql 不存在,请重新执行:

sudo yum reinstall -y mysql-community-client

步骤 6:【主库 & 从库】初始化并启动 MySQL(首次)

# 创建数据目录(systemd 启动时会自动初始化,但手动更可控)
sudo mkdir -p /var/lib/mysql
sudo chown mysql:mysql /var/lib/mysql

# 启动服务(首次启动会自动生成临时 root 密码)
sudo systemctl start mysqld

# 设置开机自启
sudo systemctl enable mysqld

# 获取临时密码
sudo grep 'temporary password' /var/log/mysqld.log

✅ 示例输出:

2025-12-01T07:40:25.096876Z 1 [Note] A temporary password is generated for root@localhost: lpiRkddQh3;A

步骤 7:【主库 & 从库】运行安全初始化(设置 root 密码)

# 执行安全脚本(按提示操作)
sudo mysql_secure_installation

交互流程建议:

  • 输入临时密码 → lpiRkddQh3;A
  • 设置新 root 密码 → 必须满足复杂度要求(如 MyNewPass!2025
  • 其余选项全部选 Y(移除匿名用户、禁用远程 root、删除 test 库、刷新权限)

🔒 完成后,root 用户只能本地登录,密码已更新。


步骤 8:【主库 & 从库】验证客户端可用性

# 尝试登录(输入刚设置的 root 密码)
mysql -u root -p -e "SELECT VERSION();"

✅ 成功输出:

+-----------+
| VERSION() |
+-----------+
| 5.7.44    |
+-----------+

❌ 若报错 Can't connect to local MySQL server through socket,创建软链接:

1sudo ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock

五、主服务器配置(master)

✅ 前提:MySQL 5.7 已按第四部分完成安装、初始化、root 密码设置,服务正常运行。

1. 修改 /etc/my.cnf 配置(核心步骤)

# 编辑 MySQL 配置文件
sudo vim /etc/my.cnf

替换或追加以下内容(重点新增 server-idlog-bin):

[mysqld]
# 基础路径(YUM 安装默认路径)
basedir=/usr
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysqld/mysqld.pid
port=3306

# 网络监听(允许远程连接)
bind-address=0.0.0.0

# 主从复制核心配置(必须!)
server-id=1                     # 主库唯一ID,必须为正整数且全局唯一
log-bin=mysql-bin               # 开启二进制日志(文件名前缀)
binlog_format=ROW               # 推荐 ROW 格式,兼容性好、数据安全

# 字符集(支持 emoji 和多语言)
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci

# 日志与安全
log-error=/var/log/mysqld.log
symbolic-links=0

[client]
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8mb4

[mysqld_safe]
log-error=/var/log/mysqld.log
socket=/var/lib/mysql/mysql.sock

💡 说明:

  • server-id=1:主库标识,从库必须不同(如 100)。
  • log-bin=mysql-bin:开启 binlog,是主从复制的 前提条件

2. 重启 MySQL 使配置生效

sudo systemctl restart mysqld
sudo systemctl status mysqld  # 确认运行正常

3. 验证 binlog 是否启用

mysql -u root -p -e "SHOW VARIABLES LIKE 'log_bin';"

✅ 正确输出:

+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin       | ON    |
+---------------+-------+

4. 创建复制专用用户

-- 登录 MySQL
mysql -u root -p

-- 创建用户(限制仅从库IP段可连接)
CREATE USER 'repl_user'@'192.168.238.%' IDENTIFIED BY 'YourPassword123!';

-- 授予最小必要权限
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.238.%';

-- 刷新权限
FLUSH PRIVILEGES;
EXIT;

🔒 安全建议:生产环境应将 % 替换为具体从库 IP,如 'repl_user'@'192.168.238.133'

5. 锁定表并记录 binlog 位置(用于初始化从库)

⚠️ 此步骤仅在使用 物理同步(rsync) 时需要。若使用 mysqldump,可跳过锁表。

-- 登录 MySQL(保持此会话不退出!)
mysql -u root -p

-- 锁定所有表(禁止写入,确保数据一致性)
FLUSH TABLES WITH READ LOCK;

-- 记录当前 binlog 文件名和位置(关键!)
SHOW MASTER STATUS;

✅ 示例输出(请记录实际值):

+------------------+----------+--------------+------------------+-------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 |      154 |              |                  |                   |
+------------------+----------+--------------+------------------+-------------------+

📌 重要:不要关闭此 MySQL 终端!锁会在会话断开时自动释放。


六、从服务器配置(slave)

✅ 前提:MySQL 5.7 已按第四部分完成安装、初始化、root 密码设置,服务正常运行。

1. 修改 /etc/my.cnf 配置

# 编辑配置文件
sudo vim /etc/my.cnf

替换或追加以下内容(修正 basedir,添加从库专属参数):

[mysqld]
# 基础路径(YUM 安装路径为 /usr)
basedir=/usr
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
pid-file=/var/run/mysqld/mysqld.pid
port=3306

# 网络监听
bind-address=0.0.0.0

# 从库核心配置
server-id=100                   # 必须与主库不同!
relay-log=/var/lib/mysql/relaylog   # 中继日志前缀
read-only=1                     # 非 SUPER 用户只读
super-read-only=1               # 包括 root 在内的所有用户只读(MySQL 5.7+)binlog_format=ROW               # 与主库一致
log-bin=mysql-bin               # 可选(若未来做级联复制则需开启)
expire_logs_days=7              # 自动清理旧日志

# 字符集
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
log-error=/var/log/mysqld.log
symbolic-links=0

[client]
socket=/var/lib/mysql/mysql.sock
default-character-set=utf8mb4

[mysqld_safe]
log-error=/var/log/mysqld.log
socket=/var/lib/mysql/mysql.sock

2. 同步主库数据(两种安全方式任选其一)

✅ 方式 A:物理同步(适用于大库,需短暂只读)

在主库操作(保持上一步的 MySQL 锁会话不退出)

# 另开一个 SSH 窗口,执行 rsync(不要停主库服务!)
sudo rsync -av /var/lib/mysql/ root@192.168.238.133:/var/lib/mysql/

在从库操作

# 修复权限
sudo chown -R mysql:mysql /var/lib/mysql

# 删除 auto.cnf(避免 UUID 冲突)
sudo rm -f /var/lib/mysql/auto.cnf

回到主库的 MySQL 会话

-- 记录 SHOW MASTER STATUS 的结果后,解锁
UNLOCK TABLES;
EXIT;
✅ 方式 B:逻辑备份(适用于小库,不停写)

在主库操作

# 导出全量数据(自动包含 binlog 位置)
mysqldump --all-databases --single-transaction --master-data=2 \
          --routines --triggers --events -uroot -p > /tmp/full.sql

# 传输到从库
scp /tmp/full.sql root@192.168.238.133:/tmp/

在从库操作

# 停止 MySQL(因要导入全量数据)
sudo systemctl stop mysqld

# 清空现有数据(可选)
sudo rm -rf /var/lib/mysql/*

# 启动服务(重建基础结构)
sudo systemctl start mysqld

# 导入数据(会自动应用 binlog 位置)
mysql -u root -p < /tmp/full.sql

3. 启动从库并验证

# 如果使用方式 A,需重启从库
sudo systemctl restart mysqld

# 验证服务状态
sudo systemctl status mysqld

七、配置主从同步(从服务器执行)

✅ 前提:已记录主库的 FilePosition(如 mysql-bin.000003, 154

-- 登录从库 MySQL
mysql -u root -p

-- 配置主库连接信息
CHANGE MASTER TO
  MASTER_HOST='192.168.238.134',
  MASTER_USER='repl_user',
  MASTER_PASSWORD='YourPassword123!',
  MASTER_PORT=3306,
  MASTER_LOG_FILE='mysql-bin.000003',   -- 替换为你记录的实际值
  MASTER_LOG_POS=154;                   -- 替换为你记录的实际值

-- 启动复制
START SLAVE;

-- 检查状态
SHOW SLAVE STATUS\G

需满足以下条件(同步成功):

  • Slave_IO_Running: Yes:从库 IO 线程正常(成功连接主库并获取 binlog);
  • Slave_SQL_Running: Yes:从库 SQL 线程正常(成功执行中继日志);
  • Seconds_Behind_Master: 0:从库无延迟(实时同步)。

3. 主服务器解锁表(同步配置完成后)

回到主库 MySQL 终端,执行以下命令释放表锁,允许写入操作:

sql

UNLOCK TABLES;

八、测试主从复制

1. 主服务器操作(写入数据)

sql

-- 创建测试数据库
CREATE DATABASE test_replication;
USE test_replication;

-- 创建测试表
CREATE TABLE test_table (
    id INT PRIMARY KEY,
    name VARCHAR(50),
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 插入测试数据
INSERT INTO test_table (id, name) VALUES (1, '测试数据1');
INSERT INTO test_table (id, name) VALUES (2, '测试数据2');

-- 确认数据插入
SELECT * FROM test_table;

2. 从服务器验证(同步数据)

sql

-- 查看是否同步了测试数据库
SHOW DATABASES;  # 应包含test_replication

-- 查看同步的数据
USE test_replication;
SELECT * FROM test_table;  # 应显示主库插入的两条数据

若从库能查询到主库插入的数据,说明主从复制配置成功!

九、常见问题排查

1. 复制错误处理(从库执行)

sql

-- 停止复制进程
STOP SLAVE;

-- 重置复制配置(谨慎使用,会清除现有同步状态)
RESET SLAVE;

-- 重新配置主从连接(参考步骤七第1点)
CHANGE MASTER TO ...;

-- 重启复制进程
START SLAVE;

2. 网络和权限检查

bash

# 检查主从网络连通性(从库ping主库)
ping 192.168.238.134

# 检查主库3306端口是否可访问(从库telnet测试)
telnet 192.168.238.134 3306

# 开放防火墙端口(若未关闭防火墙)
firewall-cmd --add-port=3306/tcp --permanent
firewall-cmd --reload

# 检查复制用户权限(主库执行)
mysql -uroot -p -e "SHOW GRANTS FOR 'repl_user'@'192.168.238.133';"

3. 端口占用问题

bash

# 检查3306端口占用情况
netstat -tulpn | grep 3306

# 终止占用进程(替换<PID>为实际进程ID)
kill -9 $(lsof -t -i:3306)

# 重启MySQL
service mysqld start

4. 日志查看(排查问题的关键)

  • 主库二进制日志:/var/lib/mysql/mysql-bin.xxxxxx(通过SHOW BINLOG EVENTS IN 'binlog.000003'查看内容);
  • 错误日志:/var/log/mysqld.log(包含启动失败、复制错误等关键信息);
  • 从库中继日志:/var/lib/mysql/relaylog.xxxxxx(通过SHOW RELAYLOG EVENTS查看内容)。

十、总结

MySQL 主从复制的核心是主库记录 binlog→从库 IO 线程获取 binlog→SQL 线程执行 binlog,搭建过程需注意以下关键点:

  1. 主从服务器server-id必须唯一,主库需开启log-bin
  2. 复制用户需授予最小权限(REPLICATION SLAVE),并限制访问 IP;
  3. 数据同步时需锁定主库表,确保一致性;
  4. 验证同步状态时重点关注Slave_IO_RunningSlave_SQL_Running是否均为Yes

通过本文的步骤,你可以快速搭建一套稳定的 MySQL 主从复制环境,实现读写分离和数据备份。生产环境中还可结合keepalived实现主从自动切换,进一步提升系统可用性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值