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(两台服务器均执行)

1. 安装 MySQL 5.7

bash

# 创建安装脚本(批量执行命令,避免手动输入错误)
vim mysql_install.sh

#!/bin/bash
# 安装依赖库(MySQL运行需要libaio)
yum install libaio -y

# 下载MySQL 5.7.44安装包(官网地址,若失效可换备用链接)
wget https://downloads.mysql.com/archives/get/p/23/file/mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz

# 备用链接(MySQL官方镜像)
# wget https://repo.mysql.com/mysql-5.7/mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz

# 解压并移动到/usr/local/mysql(标准安装路径)
tar -xf mysql-5.7.44-linux-glibc2.12-x86_64.tar.gz
rm -rf /usr/local/mysql  # 清理旧安装目录
mv mysql-5.7.44-linux-glibc2.12-x86_64 /usr/local/mysql

# 创建mysql系统用户(无登录权限,用于运行MySQL服务)
useradd -r -s /sbin/nologin mysql

# 清理旧配置并创建数据目录
rm -rf /etc/my.cnf       # 删除系统默认配置文件
cd /usr/local/mysql
mkdir mysql-files        # 创建MySQL文件目录(用于secure_file_priv参数)
chown mysql:mysql mysql-files  # 设置目录权限
chmod 750 mysql-files

# 赋予脚本执行权限并运行
chmod +x mysql_install.sh
./mysql_install.sh

2. 初始化与配置

bash

# 初始化MySQL(生成临时密码,--user指定运行用户,--basedir指定安装目录)
cd /usr/local/mysql
bin/mysqld --initialize --user=mysql --basedir=/usr/local/mysql &> /root/password.txt
bin/mysql_ssl_rsa_setup --datadir=/usr/local/mysql/data  # 生成SSL/RSA证书(用于加密连接)

# 查看初始密码(务必记录,登录MySQL需使用)
cat /root/password.txt

# 配置MySQL服务并启动
cp support-files/mysql.server /etc/init.d/mysqld  # 复制服务脚本
service mysqld start                               # 启动服务

# 确认3306端口监听(验证MySQL是否启动成功)
netstat -tulpn | grep 3306  # 应显示mysqld进程监听3306端口

# 配置环境变量(将MySQL命令添加到系统PATH,避免每次输入绝对路径)
echo 'export PATH=$PATH:/usr/local/mysql/bin' >> /etc/profile
source /etc/profile  # 使环境变量生效

# 安全配置(必做!加固MySQL安全,按提示操作)
mysql_secure_installation  
# 操作步骤:输入初始密码→设置新root密码→删除匿名用户→禁止root远程登录→删除test库→刷新权限

五、主服务器配置(master)

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

bash

# 编辑MySQL配置文件(/etc/my.cnf是MySQL默认读取的配置路径)
vim /etc/my.cnf

# 配置内容如下(带详细注释):
[mysqld]
# 基础路径配置
datadir=/var/lib/mysql                  # 数据存储目录(需确保mysql用户有读写权限)
socket=/var/lib/mysql/mysql.sock        # 服务端socket文件路径(与客户端保持一致)
basedir=/usr/local/mysql                # MySQL安装根目录
pid-file=/var/run/mysqld/mysqld.pid     # PID文件路径(记录服务进程ID)
port=3306                               # 监听端口(默认3306)

# 网络配置
bind-address=0.0.0.0                    # 允许所有IP访问(生产环境可指定从库IP)

# 主从复制核心配置
log-bin=mysql-bin                       # 开启二进制日志(主库必须开启,命名为mysql-bin)
server-id=10                            # 主库唯一ID(建议1-100,从库需不同)
binlog_format=ROW                       # 日志格式(ROW模式记录行变更,最安全,适合复制)
expire_logs_days=7                      # 日志自动过期时间(7天,避免日志文件占满磁盘)
character-set-server=utf8mb4            # 默认字符集(utf8mb4支持emoji等特殊字符)
collation-server=utf8mb4_unicode_ci     # 字符集排序规则
log-error=/var/log/mysqld.log           # 错误日志路径(便于排查问题)
symbolic-links=0                        # 禁用符号链接(避免数据目录被篡改)

# 客户端配置(解决socket路径不匹配导致的连接错误)
[client]
socket=/var/lib/mysql/mysql.sock        # 与服务端socket路径一致

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

bash

# 重启MySQL使配置生效(修改my.cnf后必须重启)
service mysqld restart

# 确认端口监听(验证服务是否正常启动)
netstat -tulpn | grep 3306

2. 创建复制用户

bash

# 登录MySQL(使用安全配置时设置的root密码)
mysql -uroot -p

# 若报错"Can't connect to local MySQL server through socket '/tmp/mysql.sock'",执行以下命令解决:
# ln -s /var/lib/mysql/mysql.sock /tmp/mysql.sock  # 创建socket软链接
# chown mysql:mysql /tmp/mysql.sock               # 设置链接权限
# 再次登录

sql

-- 创建复制用户(仅允许从库IP段访问,增强安全性,替换%为具体从库IP更佳)
CREATE USER 'repl_user'@'192.168.238.%' IDENTIFIED BY 'YourPassword123!';  # 密码需复杂,避免破解

-- 授予复制权限(仅授予REPLICATION SLAVE,最小权限原则)
GRANT REPLICATION SLAVE ON *.* TO 'repl_user'@'192.168.238.%';
FLUSH PRIVILEGES;  # 刷新权限使配置生效

3. 锁定表并记录日志状态

sql

-- 锁定所有表(禁止写入操作,确保数据一致性,避免备份时数据变更)
FLUSH TABLES WITH READ LOCK;

-- 查看二进制日志状态(记录File和Position值,后续从库配置需用)
SHOW MASTER STATUS;

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

plaintext

+---------------+----------+--------------+------------------+-------------------+
| File          | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| binlog.000003 |      154 |              |                  |                   |
+---------------+----------+--------------+------------------+-------------------+
  • File:当前正在写入的 binlog 文件名(如 binlog.000003);
  • Position:binlog 的当前位置(如 154);
  • 注意:锁定表后不要关闭 MySQL 终端,否则锁会释放,需保持终端打开直到数据同步完成。

六、从服务器配置(slave)

1. 修改 my.cnf 配置

bash

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

# 配置内容如下:
[mysqld]
# 基础路径配置(与主库保持一致)
datadir=/var/lib/mysql                  # 数据目录(需与主库同步,后续会复制主库数据)
socket=/var/lib/mysql/mysql.sock        # 服务端socket路径
basedir=/usr/local/mysql                # 安装根目录
pid-file=/var/run/mysqld/mysqld.pid     # PID文件路径
port=3306                               # 与主库端口一致

# 网络配置
bind-address=0.0.0.0                    # 允许远程访问(便于管理)

# 从库核心配置
relay-log=/var/lib/mysql/relaylog       # 中继日志路径(存储主库binlog副本)
relay-log-index=/var/lib/mysql/relaylog.index  # 中继日志索引文件
log-bin=mysql-bin                       # 级联复制时开启(普通从库可选,若从库作为其他库的主库则必须开启)
server-id=100                           # 从库唯一ID(必须与主库不同,建议100+)
binlog_format=ROW                       # 与主库保持一致
expire_logs_days=7                      # 日志过期时间
read-only=1                             # 从库只读(非root用户无法写入,防止误操作)
super-read-only=1                       # 从库只读(包括root用户,MySQL 5.7+特性,增强安全性)
character-set-server=utf8mb4
collation-server=utf8mb4_unicode_ci
log-error=/var/log/mysqld.log
symbolic-links=0

# 客户端配置(解决socket路径不匹配)
[client]
socket=/var/lib/mysql/mysql.sock

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

2. 同步主库数据(关键步骤)

主服务器操作:

bash

# 停止主库(确保数据复制时无写入操作,保持一致性)
service mysqld stop

# 删除auto.cnf(避免UUID冲突,从库启动时会自动生成新UUID)
rm -rf /var/lib/mysql/auto.cnf

# 安装rsync(用于高效同步数据,主从均需安装)
yum install -y rsync

# 同步主库数据到从库(替换从库IP和路径,-av表示归档+详细输出)
rsync -av /var/lib/mysql/ root@192.168.238.133:/var/lib/mysql/

# 启动主库(数据同步完成后恢复服务)
service mysqld start

# 确认主库端口监听
netstat -tulpn | grep 3306
从服务器操作:

bash

# 修复数据目录权限(rsync同步后权限可能异常,需设置为mysql用户)
chown -R mysql:mysql /var/lib/mysql

# 创建中继日志目录并授权(确保从库可写入中继日志)
mkdir -p /var/lib/mysql/relaylog
chown -R mysql:mysql /var/lib/mysql/relaylog
chmod 755 /var/lib/mysql/relaylog

# 创建PID目录并授权(避免启动时权限不足)
mkdir -p /var/run/mysqld
chown -R mysql:mysql /var/run/mysqld
chmod 755 /var/run/mysqld

# 启动从库
service mysqld start

# 确认从库端口监听
netstat -tulpn | grep 3306

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

1. 配置主从连接

bash

# 登录从库MySQL(使用从库root密码)
mysql -uroot -p

sql

-- 配置主库信息(替换为实际值,与主库SHOW MASTER STATUS结果对应)
CHANGE MASTER TO 
MASTER_HOST='192.168.238.134',      # 主库IP地址
MASTER_USER='repl_user',            # 主库创建的复制用户
MASTER_PASSWORD='YourPassword123!', # 复制用户密码
MASTER_PORT=3306,                   # 主库端口
MASTER_LOG_FILE='binlog.000003',    # 主库SHOW MASTER STATUS中的File值
MASTER_LOG_POS=154;                 # 主库SHOW MASTER STATUS中的Position值

-- 启动从库复制进程(开始同步数据)
START SLAVE;

2. 验证同步状态(关键!)

sql

-- 查看从库状态(重点关注Slave_IO_Running和Slave_SQL_Running)
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实现主从自动切换,进一步提升系统可用性。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值