Last_IO_Error : Error reconnecting to source
'repluser@10.0.0.12:3306' . This was attempt 1 / 86400 , with a delay of 60 seconds
between attempts. Message : Can 't connect to MySQL server on ' 10.0.0.12 : 3306 '
(111)
结果显示: 等待 60 s 之后,再来重试
3.有数据一主一从
将现在单机服务变成主从服务。
如果数据库在运行了一段时间后,己经产生了大量数据,或者重置了二进制日志,刷新了二进制日志的情况下,我们要配置主从,则要保证将己有的数据先备份出来,导入到从节点之后,再开启主从同步。
目前master节点是有数据的,我们可以将 从节点环境清空,从而实现,两者环境的不一致效果
从节点环境清空
[root @rocky9-15 ~ ] # systemctl stop mysqld
[root @rocky9-15 ~ ] # rm -rf /var/lib/mysql/*
[root @rocky9-15 ~ ] # rm -rf /data/mysql/logbin/*
[root @rocky9-15 ~ ] # systemctl start mysqld
主节点重置
重置二进制日志,如果从当前使用位置开始同步,则原有数据无法同步
reset master; #重置二进制日志文件
show slave hosts; #Empty set, 1 warning (0.01 sec)
show master status; #查看当前主服务器的状态信息
全量数据同步
用全量备份的方式导出所有己有数据,并刷新二进制日志
[root @rocky9-12 ~ ] # mysqldump -A -F --source-data=1 --single-transaction
>all.sql
注意:
- A 或 -- all-databases : mysqldump 备份 MySQL 服务器上的所有数据库。
-F 或 -- flush-logs :在执行备份之前, MySQL 服务器刷新并重置它的日志文件。
-- source-data = 1 的作用是,在导出数据的时候,记录二进制位置
-- single-transaction : mysqldump 创建一个单独的事务来导出数据,从而不需要锁定表。
确认效果
[root@rocky9-12 ~]# ll all.sql
show master logs; # 主节点确认日志效果
[root@rocky9-12 ~]#more all.sql #查看备份文件
......
......
CHANGE MASTER TO MASTER_LOG_FILE = 'mysql-bin.000002' , MASTER_LOG_POS = 157 ; # 非注释的第一行
[root @rocky9-12 ~ ] # scp all.sql 10.0.0.15: # 将备份文件复制到从节点
主节点同步账号授权
账号授权操作 - 如果存在的话,可以不用重复创建
mysql> create user repluser@'10.0.0.%' identified by '123456';
mysql> grant replication slave on *.* to repluser@'10.0.0.%';
确认效果
mysql> select user,host from mysql.user;
从节点配置
下面的内容配置过 所以就不再配置了
vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
server-id=183
read-only
log-bin=/data/mysql/logbin/mysql-bin
default_authentication_plugin=mysql_native_password # 避免出现认证问题
修改备份文件
[root @rocky9-15 ~ ] # vim all.sql
.. .
# CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=157;
# 将此句补全为如下样式
CHANGE MASTER TO
MASTER_HOST = '10.0.0.12' ,
MASTER_USER = 'repluser' ,
MASTER_PASSWORD = '123456' ,
MASTER_PORT = 3306 ,
MASTER_LOG_FILE = 'mysql-bin.000002' , MASTER_LOG_POS = 157 ;
从节点加载语句
因为是导数据,所以需要关闭二进制日志
mysql > set sql_log_bin = 0 ;
开始导入数据
mysql > source / root / all.sql
mysql > show slave status \ G #查看主从状态 (下面仅截取部分信息进行解释)
Slave_IO_Running : No # 主从环境导入成功了
start slave; # 从节点启动同步线程
show slave status \ G #查看主从状态 (下面仅截取部分信息进行解释)
Slave_IO_Running : Yes # 主从环境恢复了
mysql > set @ @sql_log_bin = 1 ; # 恢复二进制日志
mysql > use db1; # 查询
mysql > select * from student;
4.一主多从实现
环境解读
一主多从,配置多个从节点即可,基于上述一主一从,再增加一个从节点
假设:10.0.0.18是另一个slave节点 前面的所有配置环境已经弄好
基础数据同步
# 主节点导出备份数据,复制到新增节点
[root @rocky9-12 ~ ] # mysqldump -A --source-data=1 --single-transaction >all.sql
[root @rocky9-12 ~ ] # scp all.sql 10.0.0.18:
从节点同步账号配置
# 在从节点上修改备份文件
[root @rocky9-18 ~ ] # vim all.sql
# CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000002', MASTER_LOG_POS=453; # 将此内
容修改为如下所示
CHANGE MASTER TO
MASTER_HOST = '10.0.0.12' ,
MASTER_USER = 'repluser' ,
MASTER_PASSWORD = '123456' ,
MASTER_PORT = 3306 ,
MASTER_LOG_FILE = 'mysql-bin.000002' , MASTER_LOG_POS = 453 ;
# 从节点启动服务,导入备份 (启动后先把二进制日志临时关闭)
[root @rocky9-18 ~ ] # systemctl start mysqld.service
mysql > set sql_log_bin = 0 ;
mysql > source / root / all.sql;
从节点启动同步操作
mysql > show slave status \ G #成功后再进行下一步
mysql > set sql_log_bin = 1 ;
数据同步测试 可以看到同步成功
5.级联复制实现
主从复制架构中,从节点从中继日志中读取到数据写入数据库后,该数据并不会写入到从节点的二进制日志中,但是在级联同步架构中,有一个中间节点的角色,该节点从主节点中同步数据,并充当其它节点的数据源,所以在此情况下,我们需要保证中间节点从主节点中同步过来的数据,同样也要写二进制日志,否则后续节点无法获取数据。
在此架构中,中间节点要开启 log_slave_updates 选项,保证中间节点复制过来的数据也能写入二进制日志,为其它节点提供数据源。
集群环境架构 之前的从节点变为中间节点
主机IP 角色 MySQL版本
10.0.0.12 master 8.0.41
10.0.0.15 middle-slave 8.0.41
10.0.0.18 slave 8.0.41
#mysql8.0 以后默认开启了此项,其它版本或 mariadb 需要手动开启,
# 中间节点要保证 : 1 开启二进制日志, 2 从主节点上同步过来的数据,要能写到二进制日志中
mysql > select @ @log_slave_updates ; 结果显示为1 表示开启
开启中继的能力
[root @rocky9-15 ~ ] # vim /etc/my.cnf.d/mysql-server.cnf
.....
[mysqld]
server-id = 183
read-only
log_slave_updates # 增加此选项
log-bin =/ data / mysql / logbin / mysql-bin
[root @rocky9-15 ~ ] # systemctl restart mysqld.service # 重启服务器环境
登录 mysql 之后,中间节点处于同步状态
mysql > show slave status \ G
........
Slave_IO_Running : Yes
Slave_SQL_Running : Yes
........
确认中间节点上有同步过来的账号信息 , 如果没有的话,需要自己单独创建即可 。
mysql > select user,host from mysql.user;
| repluser | 10.0.0 . % #有了这个信息就行
拷贝数据
# 导出中间节点数据
[root @rocky9-15 ~ ] # mysqldump -A -F --single-transaction --source-data=1 > middle-all.sql
# 拷贝至 10.0.0.18 从节点
[root@rocky9-15 ~] # scp middle-all.sql 10.0.0.18:
1. STOP SLAVE
功能:暂停从服务器的复制线程,但保留复制状态(如二进制日志位置、主服务器连接信息等)。
两个关键线程:IO 线程:负责从主服务器读取二进制日志(binlog)。 SQL 线程:负责在从服务器上执行读取到的日志事件。2.RESET SLAVE ALL
功能:
彻底清除从服务器的复制配置,包括:
删除所有复制相关的元数据(如 master.info 和 relay-log.info 文件)。
重置复制状态(如二进制日志位置、主服务器连接信息)。
释放主服务器上的复制账号锁(重要区别!)。
重置 10.0.0.18 节点的环境
[root @rocky9-18 ~ ] # systemctl stop mysqld
[root @rocky9-18 ~ ] # rm -rf /var/lib/mysql/*
[root @rocky9-18 ~ ] # rm -rf /data/mysql/logbin/*
[root @rocky9-18 ~ ] # systemctl start mysqld.service
修改配置 -- 内容一样的话, 暂时不需要动
# 修改配置
[root @rocky9-18 ~ ] # cat /etc/my.cnf
......
[mysqld]
server-id = 186
read-only
log-bin =/ data / mysql / logbin / mysql-bin
同步账号配置
修改同步配置文件
# 修改备份文件
[root @rocky9-18 ~ ] # vim middle-all.sql (此文件是从文件生成传递的)
# CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000003', MASTER_LOG_POS=157;
# 修改上面语句为
CHANGE MASTER TO
MASTER_HOST = '10.0.0.15' ,
MASTER_USER = 'repluser' ,
MASTER_PASSWORD = '123456' ,
MASTER_PORT = 3306 ,
MASTER_LOG_FILE = 'mysql-bin.000003' ,
MASTER_LOG_POS = 157 ;
# 启动服务
[root @rocky9-18 ~ ] # systemctl start mysqld.service
# 临时关闭二进制日志
mysql > set sql_log_bin = 0 ;
从节点导入数据
# 导入备份数据
mysql > source / root / middle-all.sql
# 开启二进制日志
mysql > set sql_log_bin = 1 ;
# 查看主从状态
mysql > show slave status \ G
Slave_IO_Running : No
Slave_SQL_Running : No
# 启动同步
mysql > start slave;
# 再次查看状态
mysql > show slave status \ G
Slave_IO_Running : Yes
Slave_SQL_Running : Yes
数据同步测试 下面的命令在主节点上进行操作
mysql > insert into student (name,age,gender)values( 'user6' , 60 , 'M' );
mysql > delete from student where id = 2 ;
结果显示 从 节点和中间节点 主节点内容都一样
验证连接信息
主节点上查看进程 , 可以看到中间节点的连接信息
[root @rocky9-12 ~ ] # ss -tnap | grep 3306
mysql > show processlist \ G -- 存在 dump 线程
Command : Binlog Dump # 将数据传递给中间节点
中间节点上查看进程 , 可以看到主节点连接信息, last 节点的连接信息
[root @rocky9-15 ~ ] # ss -tnap | grep 3306
mysql > show processlist \ G --- 存在 dump 线程、 io 线程、 sql 线程
State : Waiting for source to send event # IO 线程,存储数据到中继日志
Command : Query # sql 线程,执行数据落地
Command : Binlog Dump # dump 线程,将数据传递给从节点
[root @rocky9 ~ ] # ss -tnap | grep 3306
......
mysql > show processlist \ G # 存在 io 线程和 sql 线程
.......
6.主主复制实现
环境解读
在双主模型中,两个节点互为主备,两个节点都要开启二进制日志,都要有写权限。
根据前面的实验, master-2 己经是 master-1 的从节点了,此处只需要把 master-1 配置为 master-2 的从节点即可。
10.0.0.18 清理从节点环境
mysql > stop slave;
mysql > reset slave all;
稍等数十秒后,在 10.0.0.15 节点上确认效果
mysql > show slave hosts;
Empty set , 1 warning ( 0.00 sec)
准备工作
master1 (根据之前的不用进行修改)
[root @rocky9-12 ~ ] # cat /etc/my.cnf.d/mysql-server.cnf
.. .
[mysqld]
server-id = 177
log_bin =/ data / mysql / logbin / mysql-bin
default_authentication_plugin = mysql_native_password
.. .
#master2 配置需要修改,去掉 read-only
[root @rocky9-15 ~ ] # cat /etc/my.cnf.d/mysql-server.cnf
......
[mysqld]
server-id = 183 # 主要是 id
log_bin =/ data / mysql / logbin / mysql-bin
default_authentication_plugin = mysql_native_password
# log_slave_updates # 停止中间服务器的能力
.. .
# 重启 master-2
[root @rocky9-15 ~ ] # systemctl restart mysqld
在 master-2 上查看 slave 状态,己经是 master-1 的从了
mysql > show slave status \ G
配置 master-1 主机为从角色 (关键)
因为两台主机的 数据都是一样 的,所以,无需重新加载数据服务了
注意 MASTER_LOG_FILE 信息可以在 show master logs 里面看
-- 配置主库信息
CHANGE MASTER TO
MASTER_HOST='10.0.0.15',
MASTER_USER='repluser',
MASTER_PASSWORD='123456',
MASTER_PORT=3306,
MASTER_LOG_FILE='mysql-bin.000005',
MASTER_LOG_POS=157;-- 启动从库复制进程
START SLAVE;-- 检查从库状态
SHOW SLAVE STATUS\G
在检查从库状态时,要重点查看以下两个参数: Slave_IO_Running: Yes Slave_SQL_Running: Yes 只有当这两个参数的值都为 'Yes' 时,主从复制才能正常工作
MASTER_LOG_FILE 文件不一致导致下面的报错

测试同步效果
master-1 进行写操作, master-2 上查看 可以看到已经同步
master-2 中删除数据 , 在 master-1中查看效果 可以看到已经同步
双主架构的注意事项
解析 : 双主架构在实际生产环境中, 并不会配置为两个节点都去写数据
双主架构在实际生产环境中,并不会配置为两个节点都去写数据,前端应用只会写一个节点,另一个节点作为备份节点,如果当前使用的节点出问题,则 IP 地址会立即转移到另一个节点上,起到一个高可用的作用,此时,如果有 slave 节点,在 slave 上要重新执行同步操作
注意:两台数据库虽然数据是一样的,但是二进制日志有可能是不一样的
show master logs; 进行查看
双主写冲突实践
尝试在两个主机同时写入数据
mysql > insert into student(name,age,gender) values( 'user8' , 80 , 'F' );
两台主机同时查看主从同步效果
mysql > show slave status \ G
结果显示:主从同步己经不能使用了
在主从同步失效的情况下,在 master-1 上的写操作,无法同步到 master-2
master1 通过忽略来解决问题
mysql > stop slave; # 停止主从
mysql > set global sql_slave_skip_counter = 1 ; # 跳过 1 个错误事件
mysql > start slave; # 再次开启主从同步
mysql > show slave status \ G # 查看同步状态,己经恢复
master2 通过忽略来解决问题
所有命令操作同上(略)
其他注意事项
忽略错误编号
除了使用 set global sql_slave_skip_counter=N 忽略错误个数之外,也可以用忽略指定错误编号的方式来处理错误。
mysql>show slave status\G
Last_SQL_Errno: 1062 # 这两个字段的值就是错误编号
#slave_skip_errors=N|ALL 用来忽略指定的错误编号,是服务器选项,要写配置文件后重启服务
[mysqld]
slave_skip_errors = N | ALL
虽然有方法解决双写出现的问题,但还是存在风险,正确的做法是禁用双写,只能写一个节点。
多次忽略错误
当 MySQL 主从复制中出现 5 条数据错误时,如果想精确控制跳过的事务,可分 5 次执行 SET
GLOBAL SQL_SLAVE_SKIP_COUNTER = 1 ; 语句。每次跳过一个错误事务后,检查复制状态,确保从库能正常继续复制。 下面的所有命令执行5次
STOP SLAVE;
SET GLOBAL SQL_SLAVE_SKIP_COUNTER = 1 (或1改成 5 #执行一次即可)
START SLAVE;
SHOW SLAVE STATUS \ G
根源修复
上述跳过事务的方法只是临时解决办法,可能会造成主从数据不一致。为了避免后续再次出现类似问题,需要找出导致复制错误的根源并进行修复。以下是一些常见的原因及解决办法:
如果上述办法都不行 则 可以考虑重新初始化从库
1 在主库上创建一个新的备份。
2 在从库上停止复制进程,清空数据。
3 将主库的备份恢复到从库。
4 重新配置主从复制,让从库从主库开始同步数据。
7.半同步复制原理解读
Mysql 8.0 半同步实践
集群环境

将 10.0.0.12 主机上的从角色清理掉
mysql > stop slave;
mysql > reset slave all;
mysql > show slave status;
Empty set , 1 warning ( 0.00 sec)
在 MySQL8.0 中配置半同步需要安装插件支持
# 安装 MySQL8.0 中己有相关插件的支持文件
rpm -ql mysql-server |grep semisync
master 节点配置插件
mysql > select * from mysql.plugin;
Empty set ( 0.00 sec) # 没有插件
在 master节点上安装 master 插件
mysql > INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so' ;
# 持久化加载插件的方法,修改配置文件 (下面有操作流程 这部现在可以先不做)
[mysqld]
rpl_semi_sync_master=semisync_master.so
所谓的安装插件,其实在 mysql 库中的 plugin 表中写入一条数据
set global rpl_semi_sync_master_enabled=1; 临时开启插件
主节点配置复制账号 - 最开始的步骤 已做
创建主从复制账号,并授权
mysql > create user repluser @'10 .0.0 . % ' identified by ' 123456 ';
mysql > grant replication slave on * . * to repluser @'10 .0.0 . % ';
master 节点启用插件
# 修改配置文件,开启插件
[root @rocky9-12 ~ ] # vim /etc/my.cnf.d/mysql-server.cnf
[mysqld]
rpl_semi_sync_master_enabled # 增加功能,注意是 master 关键字
重启服务 [root @rocky9-12 ~ ] # systemctl restart mysqld.service
# 再次查看,需要稍等几秒钟
select @@rpl_semi_sync_master_enabled; 值为1 说明已经开启
slave 节点启用插件 (和master相同的步骤不同点我会放在地下)
# 在 slave 节点上安装 slave 插件
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so' ;
# 修改配置文件,开启插件
[root @rocky9-15 ~ ] # vim /etc/my.cnf.d/mysql-server.cnf
......
[mysqld]
server-id = 183
read-only
log-bin =/ data / mysql / logbin / mysql-bin
rpl_semi_sync_slave_enabled # 增加该条属性,注意是 slave 关键字
# 重启服务
[root@rocky9-15 ~] # systemctl restart mysqld;
另一台主机执行相同操作
另一台 slave 节点配置同上,注意修改 server-id (其他的和上个slave 配置一样)
清理环境服务
[root @rocky9-18 ~ ] # systemctl stop mysqld.service
[root @rocky9-18 ~ ] # rm -rf /var/lib/mysql/*
[root @rocky9-18 ~ ] # rm -rf /data/mysql/logbin/*
[root @rocky9-18 ~ ] # systemctl start mysqld.service
启用插件,不先启用插件,则后面修改配置后,无法使用
mysql > INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so' ;
修改配置文件 ,
rpl_semi_sync_slave_enabled # 增加该条属性
重启服务 [root @rocky9-18 ~ ] # systemctl restart mysqld.service
在 slave 节点上开启主从
主节点导出数据
[root @rocky9-12 ~ ] # mysqldump -A -F --source-data=1 --single-transaction>all.sql
[root @rocky9-12 ~ ] # scp all.sql root@10.0.0.18:
slave 节点修改配置
[root @rocky9-18 ~ ] # vim all.sql .. . # CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000004', MASTER_LOG_POS=157; # 修改为如下数据
CHANGE MASTER TO MASTER_HOST = '10.0.0.12' , MASTER_USER = 'repluser' , MASTER_PASSWORD = '123456' , MASTER_PORT = 3306 , MASTER_LOG_FILE = 'mysql-bin.000004' , MASTER_LOG_POS = 157
在 slave 节点上开启主从
mysql > set sql_log_bin = 0 ;
mysql > source / root / all.sql;
mysql > set sql_log_bin = 1 ;
启用从服务
mysql > start slave;
# 查看状态
mysql > show slave status \ G
......
Slave_IO_Running : Yes
Slave_SQL_Running : Yes
master 确认信息
show global status like '%semi%' ;
show global variables like '%semi%' ;
数据同步测试
测试,在master 节点上写入数据
结果显示 slave-1节点和slave-2节点 看到的效果相同
测试单个 slave 可用
测试,半同步状态下,只要有一个 slave 节点能同步到数据, master 节点就能返回成功
# 在 slave-1 节点上停止 mysq 服务
[root @rocky9-15 ~ ] # systemctl stop mysqld
在 master 节点上查看,还有一个 slave 节点 ( 数据有延时,要等一会儿 ) ,也就十几秒左右的时间
mysql > show global status like '%Rpl_semi_sync_master_clients%' ; 得到值为1
。。。。
master 节点写入数据,返回成功,只要有一个 slave 节点同步成功即可
mysql > insert into student(name,age,gender)values( 'user2' , 20 , 'M' );
结果显示 #slave-2 节点上同步成功
测试没有 slave 可用
[root @rocky9-18 ~ ] # systemctl stop mysqld
# 再次在 master 节点上查看,己经没有 slave 在线
mysql > show global status like '%Rpl_semi_sync_master_clients%' ; 得到值为0
# 再次执行写操作,没有 slave 节点在线,等 10S 后超时,但 master 节点上写入成功
mysql> insert into student(name,age,gender)values( 'user3' ,30, 'M' );
# ... 这个地方需要阻塞 10s 后,再返回信息
Query OK, 1 row affected (10.01 sec)
# 查看超时时长
mysql > show variables like '%semi_sync_master_timeout%' ; 得到值为10000
修改同步超时时长 [root @rocky9-12 ~ ] # vim /etc/my.cnf.d/mysql-server.cnf
rpl_semi_sync_master_timeout = 3000 # 设定时间为 3秒 将同步超时时长改为 3S
重启服务 systemctl restart mysqld;
show variables like '%semi_sync_master_timeout%' ; 得到值为3000
# 测试, 3S 超时
mysql > insert into student(name,age,gender)values( 'user4' , 40 , 'M' );
# ... 这个地方需要阻塞 3s 后,再返回信息
Query OK, 1 row affected ( 3.00 sec)
恢复 slave-1,master 节点再次写数据,立即成功
8. 复制过滤器 【K】
10.0.0.12 master
10.0.0.15 slave-1
#master 节点上配置 db1,db2 不写二进制日志
[root @rocky9-12 ~ ] # vim /etc/my.cnf.d/mysql-server.cnf
binlog-ignore-db = db1
binlog-ignore-db = db2
重启 mysql 服务之后 生效
master 配置未生效的时候, slave 可以看效果
# 在 master 节点上为 db1 写入数据
mysql > use db1;
9.GTID 复制