前言:
MySQL 主从同步是生产环境中最常用的高可用方案之一,也是运维工程师必备的基础技能。然而在实际搭建过程中,备份时机、binlog 位置、用户创建顺序等细节问题常常导致复制链路失败。
本文基于实际生产经验,整理出一套标准化的 MySQL 主从同步操作流程(SOP),每一步都经过验证,确保“按步骤做就能成功”。
一、环境准备
| 主机 | IP地址 |
|---|---|
| mysql1 | 192.168.88.10 |
| mysql2 | 192.168.88.11 |
二、主服务器配置
#1.修改配置文件
[root@mysql1 ~]# vim /etc/my.cnf.d/mysql-server.cnf
server-id=10 #集群唯一标识
log_bin=/data/mysql/binlog/mysql-bin #开启并指定binlog位置
binlog_format=ROW #行级复制,生产首推
binlog_row_image=FULL #修改一行数据时,把该行所有字段的值全部写入binlog。
gtid_mode=ON #开启gtid
enforce_gtid_consistency=ON #与gtid搭配,强制sql符合gtid规范
sync_binlog=1 #每次事务提交立即刷binlog到磁盘
innodb_flush_log_at_trx_commit=1 #每次事务提交立即刷redo log到磁盘
expire_logs_days=7 #binlog保留7天
max_binlog_size=1G #单binlog最大1G
#半步同步:至少有一个从库确认收到数据后,主库才返回"写入成功"。
plugin-load-add=rpl_semi_sync_source=semisync_source.so #mysql启动时指定加载插件
rpl_semi_sync_source_timeout=10000 #主库等待从库回复‘确认收到数据’的时间
rpl_semi_sync_source_enabled=1 #值为1表示主库开启半步同步
rpl_semi_sync_source_wait_for_replica_count=1 #至少一台从库确认收到数据,主库才返回成功
bind-address=192.168.88.10
port=3306
innodb_buffer_pool_size=1G #缓存池大小1G
innodb_file_per_table=1 #每张表独立文件存储
log_bin_trust_function_creators=1 #允许 GTID 下创建存储过程/函数
#2.创建存放binlog日志的目录、修改属主属组、权限
[root@mysql1 ~]# mkdir -p /data/mysql/binlog
[root@mysql1 ~]# chown -R mysql:mysql /data/mysql/binlog
[root@mysql1 ~]# chmod 0700 /data/mysql/binlog
#3.检查binlog日志是否开启:
[root@mysql1 ~]# mysql -e "show variables like 'log_bin'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| log_bin | ON |
+---------------+-------+
#ON为已开启binlog,OFF则是没有开启
#4.重启mysqld服务
[root@mysql1 ~]# systemctl restart mysqld
#5.创建用于主从同步的用户:
[root@mysql1 ~]# mysql -e "create user replicauser1@'192.168.88.11' identified by'123456';"
[root@mysql1 ~]# mysql -e "create user replicauser2@'192.168.88.12' identified by'123456';"
#注意:MySQL的用户完整标识是 用户名@登录主机,用户名相同、host不同 = 两个完全独立账号。
#6.给主从同步的用户授权:
[root@mysql1 ~]# mysql -e "grant replication slave on *.* to replicauser1@'192.168.88.11'"
[root@mysql1 ~]# mysql -e "grant replication slave on *.* to replicauser2@'192.168.88.12'"
#*.*代表所有库和所有表
#7.检查主服务器是否配置ssl证书:
[root@mysql1 ~]# mysql -e "show variables like '%ssl'"
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| have_openssl | YES |
| have_ssl | YES |
+---------------+-------+
#YES表示配置了ssl证书
8.对数据全量备份:
[root@mysql1 ~]# mysqldump -A > all.sql
#-A表示备份全部数据
9.将备份的数据发给从服务器:
[root@mysql1 ~]# scp all.sql root@192.168.88.11:/root
[root@mysql1 ~]# scp all.sql root@192.168.88.12:/root
10.查看主服务器信息:
[root@mysql1 ~]# mysql -e "show master status;"
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000001 | 729 | | | |
+------------------+----------+--------------+------------------+-------------------+
#file:当前正在写入的binlog文件名(从库配置source_log_file要填这个名字)
#Position:binlog当前写入位置偏移量(从库source_log_pos填这个)
三、从服务器1配置
1.修改从服务器配置文件:
[root@mysql2 ~]# vim /etc/my.cnf.d/mysql-server.cnf
server-id=12 #集群唯一标识
gtid_mode=ON #开启GTID全局事务标识
enforce_gtid_consistency=ON #强制GTID一致性
relay_log=/data/mysql/relay/relay-bin #指定中继日志存放位置
relay_log_recovery=ON #从库奔溃自动清除无效relay log
read_only=ON #禁止普通用户写入从库
super_read_only=ON #禁止超级用户写入从库
slave_parallel_type=LOGICAL_CLOCK #基于主库提交的并行复制模式
slave_parallel_workers=4 #并行回放线程
slave_preserve_commit_order=ON #保证并行回放时事务提交顺序和主库一致
plugin-load-add=rpl_semi_sync_replica=semisync_replica.so #加载该模块
rpl_semi_sync_replica_enabled=1 #开启半步同步
2.创建存放中继日志的目录,修改属主属组
[root@mysql2 ~]# mkdir -p /data/mysql/relay
[root@mysql2 ~]# chown -R mysql:mysql /data/mysql
3.重启mysqld服务:
[root@mysql2 ~]# systemctl restart mysqld
4.导入备份过来的数据:
[root@mysql2 ~]# mysql < all.sql
5.验证数据是否导入成功:
[root@mysql2 ~]# mysql -e "select user,host from mysql.user;"
+------------------+---------------+
| user | host |
+------------------+---------------+
| replicauser1 | 192.168.88.11 |
| replicauser2 | 192.168.88.12 |
| mysql.infoschema | localhost |
| mysql.session | localhost |
| mysql.sys | localhost |
| root | localhost |
+------------------+---------------+
6.进入mysql配置主服务器信息:
[root@mysql2 ~]# mysql
mysql> change replication source to #修改主从同步主库信息
source_host="192.168.88.10", #主库地址
source_port=3306, #主库端口
source_user="repilicauser1", #用于主从同步的用户(故意写错用户)
source_password="123456", #用于主从同步用户的密码
source_ssl=1, #主服务器没开启则不需要加
source_auto_position=1; #使用GTID自动定位
Query OK, 0 rows affected, 2 warnings (0.44 sec)
7.启动IO/SQL线程:
mysql> start replica;
8.验证主从同步是否设置成功:
mysql> show replica status\G
*************************** 1. row ***************************
Replica_IO_State: Connecting to source #IO线程一直尝试连接主库
Source_Host: 192.168.88.10 #主库IP地址
Source_User: repilicauser1 #连接主库的用户名
Source_Port: 3306 #主库mysql的端口号
Connect_Retry: 60 #连接失败再次连接的间隔
Source_Log_File: mysql-bin.000001 #主库binlog日志文件名
Read_Source_Log_Pos: 729 #IO线程读到主库的段偏移量
Relay_Log_File: relay-bin.000001 #从库中继日志文件名
Relay_Log_Pos: 4 #中继日志回放位置
Relay_Source_Log_File: mysql-bin.000001 #中继日志对应主库原始的binlog文件
Replica_IO_Running: Connecting #正在尝试连接
Replica_SQL_Running: Yes #sql回放线程运行状态
9.下拉查看错误信息:
Replica_IO_Running: Connecting
Replica_SQL_Running: Yes
#IO线程正在连接
#SQL线程状态正常
Last_IO_Errno: 1045
# IO线程最近一次错误编号:1045
Last_IO_Error: Error connecting to source 'repilicauser1@192.168.88.10:3306'.
This was attempt 1/86400, with a delay of 60 seconds between attempts.
Message: Access denied for user 'repilicauser1'@'mysql2' (using password: YES)
#错误信息可以直接发给AI,由AI解读
Last_SQL_Errno: 0
#回放线程无错误
Last_SQL_Error:
#回放线程无错误信息
10.停止IO/SQL线程
mysql> stop replica;
11.重置从服务器信息:
mysql> reset replica all;
12.重新配置主服务器信息:
[root@mysql2 ~]# mysql
mysql> change replication source to #修改主从同步主库信息
source_host="192.168.88.10", #主库地址
source_port=3306, #主库端口
source_user="replicauser1", #用于主从同步的用户(写正确的用户名)
source_password="123456", #用于主从同步用户的密码
source_ssl=1, #主服务器没开启则不需要加
source_auto_position=1; #使用GTID自动定位
Query OK, 0 rows affected, 2 warnings (0.44 sec)
13.启动IO/SQL线程:
mysql> start replica;
14.验证主从同步是否设置成功:
mysql> show replica status\G
*************************** 1. row ***************************
Replica_IO_State: Waiting for source to send event
#等待主库推送新数据,表示连接主库成功
15.下拉查看信息:
Replica_IO_Running: Yes
Replica_SQL_Running: Yes
#一切正常
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
#一切正常
四、验证主从同步效果
1.mysql1创建库表,插入数据
[root@mysql1 ~]# mysql -e "create database hello;"
[root@mysql1 ~]# mysql -e "create table hello.hi(id int,name char(10));"
[root@mysql1 ~]# mysql -e "insert into hello.hi values (1,zhangsan)"
[root@mysql1 ~]# mysql -e "insert into hello.hi values (1,'zhangsan')"
2.mysql2查看数据,验证结果
[root@mysql2 ~]# mysql -e "show databases;"
+--------------------+
| Database |
+--------------------+
| hello |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
[root@mysql2 ~]# mysql -D hello -e "show tables;"
+-----------------+
| Tables_in_hello |
+-----------------+
| hi |
+-----------------+
[root@mysql2 ~]# mysql -e "select * from hello.hi"
+------+----------+
| id | name |
+------+----------+
| 1 | zhangsan |
+------+----------+
5、从服务器2配置
1.将从服务器1的配置文件与备份的数据拷贝过来
[root@mysql3 ~]# scp root@192.168.88.11:/etc/my.cnf.d/mysql-server.cnf /etc/my.cnf.d/mysql-server.cnf
2.导入数据
[root@mysql2 ~]# mysql < all.sql
3.修改配置文件的server_id
[root@mysql3 ~]# sed -i 's/^server-id=11/server-id=12/' /etc/my.cnf.d/mysql-server.cnf
4.重启mysqld
[root@mysql3 ~]# systemctl restart mysqld
5.重新配置主服务器信息:
[root@mysql2 ~]# mysql
mysql> change replication source to #修改主从同步主库信息
source_host="192.168.88.10", #主库地址
source_port=3306, #主库端口
source_user="replicauser2", #用于主从同步的用户(写正确的用户名)
source_password="123456", #用于主从同步用户的密码
source_ssl=1, #主服务器没开启则不需要加
source_auto_position=1; #使用GTID自动定位
6.启动IO/SQL线程:
mysql> start replica;
7.验证主从同步是否设置成功:
mysql> show replica status\G
结语:
以上就是 MySQL 主从复制的完整搭建流程。核心要点可以总结为三句话:
-
先开 binlog + 建用户 → 备份数据(备份文件必须包含 binlog 位置和复制用户)
-
从库先配 server_id → 恢复数据 → 启动复制
-
最后必须用 SHOW REPLICA STATUS 验证双 Yes,才算真正成功