mysql主从复制之异步复制

异步复制(Asynchronous Replication) 是 MySQL 主从复制的 默认模式,也是最基础、最常用的复制模式。其核心特点是 主库写入 binlog 后无需等待从库响应,直接返回成功给客户端,性能最高但存在一定的数据丢失风险。

核心流程

异步复制的流程延续主从复制的 3 线程架构,但主库与从库之间无任何同步等待机制:

  1. 主库执行用户的 INSERT/UPDATE/DELETE 操作,事务提交时将变更写入 binlog。
  2. 主库完成 binlog 写入后,立即返回成功给客户端,不等待从库同步。
  3. 从库的 IO 线程 异步请求主库的 binlog,主库的 dump 线程 发送 binlog 事件给从库。
  4. 从库 IO 线程将接收的 binlog 写入 relay log,SQL 线程异步读取 relay log 并重放,实现数据同步。

核心特点

特点 说明
主库不等待从库 主库性能不受从库影响,这是异步复制性能最高的关键原因
数据一致性弱 主库宕机时,可能存在部分 binlog 未发送到从库,导致从库数据丢失
延迟不可控 从库同步完全异步,高并发场景下延迟可能持续增大
架构最简单 无需额外配置,默认开启,运维成本低

与半同步复制的区别

对比维度 异步复制 半同步复制
主库返回时机 写入 binlog 后立即返回 至少等待 1 个从库接收并写入 relay log 后返回
数据安全性 低(可能丢失数据) 高(主库宕机时数据不丢失)
性能 最高(无等待开销) 略低(需等待从库响应)
适用场景 对性能要求高、数据丢失风险可接受的场景(如普通业务系统) 对数据安全性要求高的场景(如金融、核心交易系统)

异步复制的配置

在 MySQL 5.7 及 8.0 中,异步复制是默认开启的。

前提:主从数据库版本一致

1、主库停服时制作主从

一、主库:192.168.15.101

1、在主库上创建一个用于复制的账号,并赋予replication slave权限,这里必须*.*不能指定库授权,因为replication slave是全局的

mysql> grant replication slave on *.* to 'mangol'@'%' identified by '123';
mysql> flush privileges;

2、修改主库配置文件,开启主库的Binlog,并设置server-id

[mysqld]
# 节点ID,确保唯一
server-id = 1        
 
#开启mysql的binlog日志功能
log-bin = mysql-bin
#控制数据库的binlog刷到磁盘上去 , 0 不控制,性能最好,1每次事物提交都会刷到日志文件中,性能最差,最安全
sync_binlog = 1     
#binlog日志格式
binlog_format = row   
#binlog过期清理时间
expire_logs_days = 7
#binlog每个日志文件大小
max_binlog_size = 100m
#binlog缓存大小
binlog_cache_size = 4m   
#最大binlog缓存大小
max_binlog_cache_size= 512m         
 
#不生成日志文件的数据库,多个忽略数据库可以用逗号拼接,或者 复制黏贴下述配置项,写多行
binlog-ignore-db=mysql 
 
# 表中自增字段每次的偏移量
auto-increment-offset = 1 
# 表中自增字段每次的自增量
auto-increment-increment = 1  
#跳过从库错误
slave-skip-errors = all 

3、重启主库

systemctl restart mysql

4、备份主库,备份时锁表保证备份一致

mysqldump -uroot -pEgon@123 -A -E -R --triggers --master-data=2 --single-transaction > /tmp/all.sql

5、将备份文件发送给从库

scp /tmp/all.sql root@192.168.15.100:/tmp

二、从库:192.168.15.100

1、测试复制账号

mysql -umangol -p123 -h 192.168.15.101

2、导入初始数据

 mysql -uroot -pMangol@123 < /tmp/all.sql 

3、修改从库配置文件,增加server-id,注意这个值是唯一的,要区别于主库和其他从库

[mysqld]
server-id = 2
 
relay-log = mysql-relay-bin
replicate-wild-ignore-table=mysql.%
replicate-wild-ignore-table=test.%
replicate-wild-ignore-table=information_schema.%
 
# 从库也可以开启binlog,但通常关闭
# log-bin=mysql-bin

4、重启从库

systemctl restart mysqld

5、配置复制
先去主库查看一下binlog日志名与位置

show master status;

然后在从库进行配置

[root@slave1 ~]# mysql -uroot -pMangol@123 # 登录然后执行
 
change master to
master_host='192.168.15.101',  -- 库服务器的IP
master_port=3306,              -- 主库端口
master_user='mangol', -- 主库用于复制的用户
master_password='123', -- 密码
master_log_file='mysql-bin.000001', -- 主库日志名
master_log_pos=120; -- 主库日志偏移量,即从何处开始复制

从库启动slave线程并检查

mysql> start slave;
Query OK, 0 rows affected (0.01 sec)

2、主库运行时制作主从

1.准备纯净的从库环境
主库:192.168.15.101
从库:192.168.15.100
 
2.修改主库配置文件(略)
3.重启主库(略)
4.主库创建账号(略)
5.模拟主库运行,有数据写入、
for i in `seq 1 1000000`
do 
    mysql -uroot -p123 -e "insert db1.t1 values($i)";
    sleep 1;
done
 
6.主库全备数据
#不打点备份(no)
mysqldump -uroot -p123 -A -R --triggers > /tmp/all.sql
#打点备份(yes)
mysqldump -uroot -p123 -A -R --triggers --master-data=2 --single-transaction > /tmp/all.sql
 
7.将热备数据传达从库
scp /tmp/all.sql 192.168.15.100:/tmp
 
8.修改从库配置文件(略)
 
9.重启从库(略)
 
10.在从库导入全备数据(导入打点备份,原因如下)
#导入不打点的数据的话,接下来主从,位置点只能去主库查看 show master status; 而数据在不停地往主库里插入,该命令查看的只是那一刻binlog的记录的位置,基于该位置同步数据会丢失所获得位置点往前一直到全备的数据,以及操作从库过程中新写入主库的数据。
 
#如果导入的是打点的数据,那么全量备份的起始点可以从备份文件中获得,从库可以以此为同步的基准点,去主库获取全量备份之后的数据
 
11.查看sql文件中的位置点(如果是打点备份的话)
该位置即主库刚刚做完全量备份时,主库binlog日志所处的位置
[root@egon ~]# head -50 /tmp/all.sql|grep 'MASTER_LOG_POS'
-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000001', MASTER_LOG_POS=129005;
 
12.从库配置同步
[root@slave1 ~]# mysql -uroot -pEgon@123 # 登录然后执行
change master to
master_host='192.168.15.101',
master_port=3306, 
master_user='egon',
master_password='123',
master_log_file='mysql-bin.000001', 
master_log_pos=129005; 
 
13.开启SQL线程和IO线程
    start slave;
14.查看主从状态
    show slave status;

3、主从复制基本故障处理

#清空主从配置
    reset slave all;

(1)IO线程问题

1.检测网络:
    [root@db01 ~]# ping 172.16.1.51
 
2.检测端口:
    [root@db01 ~]# telnet 172.16.1.51 3307
    #阿里云机器有的禁ping
    [root@db01 ~]# tcping 172.16.1.51 3306
 
3.检测账号,密码:
    #根据授权命令
    grant replication slave on *.* to rep@'172.16.1.5%' identified by '123';
    #连接测试
    mysql -urep -p123 -h127.0.0.1 -P 3307
 
4.查看binlog是否存在
    show master status;
 
5.反向解析
    #没有跳过反向解析
    ERROR 1045 (28000): Access denied for user 'root'@'db01' (using password: YES)
    #配置
    skip_name_resolve

(2)SQL线程问题

1.主库有的数据,从库没有
    主库:a库
    从库:没有a库
2.从库有的数据,主库没有
    从库:a库
    主库:要创建a库
3.主库与从库数据库结构有差别
 
#处理方法一:
    #临时停止同步
    mysql> stop slave;
    #将同步指针向下移动一个(可重复操作)解决不了根本问题
    mysql> set sql_slave_skip_counter=1;
    #开启同步
    mysql> start slave;
 
#处理方法二:
    #编辑配置文件
    [root@db01 ~]# vim /etc/my.cnf
    #在[mysqld]标签下添加以下参数
    slave-skip-errors=1032,1062,1007
        1007:对象已存在
 
        1032:无法执行DML
 
        1062:主键冲突,或约束冲突
 
#处理方法三:
    1.要求,主从复制之前,主库和从库的数据保证一致.
    2.在从库上设置  只读:set read-only=1;
    (做读写分离时使用,但是做MHA会出现提升为主库时,主库只读,后面会讲专门做读写分离的Atlas)

4、延迟从库

我们说用延时从库可以做备份,主库执行删除的时候,从库还没有删除,可以把表数据拿出来恢复回去

企业中一般会延时3-6小时

延迟从库配置

已经有主从的情况下

1.停止主从
    mysql> stop slave;
2.设置延时为180秒
    mysql> CHANGE MASTER TO MASTER_DELAY = 180;
3.开启主从
    mysql> start slave;
4.查看状态
    mysql> show slave status \G
    SQL_Delay: 180
5.主库创建数据,会看到从库值变化,创建的库没有创建
    SQL_Remaining_Delay: 170

没有主从的情况下

1.修改主库,从库配置文件
    server_id
    开启binlog
 
2.保证从库和主库的数据一致
 
3.执行change语句
    change master to
    master_host='172.16.1.50',
    master_user='rep',
    master_password='123',
    master_log_file='mysql-bin.000001',
    master_log_pos=2752,
    master_delay=180;

延时从库停止方法

1.停止主从
mysql> stop slave;
 
2.设置延时为0
mysql> CHANGE MASTER TO MASTER_DELAY = 0;
 
3.开启主从
mysql> start slave;
 
#注:做延时从库只是为了备份,不提供服务

(2) 思考:延时到底是在哪里延时的

思考:IO线程还是SQL线程做的手脚?
 
#去主库创建一个库
    create database ttt;
#查看从库的relaylog看看有没有内容
    mysqlbinlog --base64-output=decode-rows -vvv db03-relay-bin.000002
 
总结:
    延时从库是在SQL线程做的手脚,IO线程已经把数据放到relay-log里了.
    SQL线程在执行的时候,会延迟你设定的时间长度.

使用延时从库恢复数据

1、场景

总数据量级500G,正常备份去恢复需要1.5-2小时
1)配置延时3600秒
mysql> CHANGE MASTER TO MASTER_DELAY = 3600;
 
2)主库
drop database db;
 
3)怎么利用延时从库,恢复数据?

2、环境准备

1.进行每日的全备
mysqldump -uroot -p123 -A -R --triggers --master-data=2 –single-transaction > /backup/full.sql
 
2.调整延时从库延时时间为60分钟
    stop slave;
    CHANGE MASTER TO MASTER_DELAY = 3600;
    start slave;
 
3.主库写入新数据
    create database yanshi;
    use yanshi;
    create table yanshi(id int);
    insert into yanshi values(1),(2),(3),(4);
 
    create database yanshi2;
    use yanshi2;
    create table yanshi2(id int);
    insert into yanshi2 values(1),(2),(3),(4);

3、模拟删除数据

1.删除一个库,可以是之前的,也可以是刚创建的
    #因为刚我们看了,只要我执行了,从库已经写到了relay-log,跟我数据库里的数据关系不大
    drop database world;

4、使用延时从库恢复数据

1.停止从库sql线程
    stop slave sql_thread;
2.查看状态
    show slave status;
3.备份从库数据
    mysqldump -uroot -p123 -B world > /backup/congku.sql
4.截取一下relay-log
    1)确认起点,查看relay-log.info即可
        [root@db02 data]# cat relay-log.info
        ./db02-relay-bin.000005
        283
    2)确认终点,找到drop语句之前
        [root@db02 data]# mysqlbinlog --base64-output=decode-rows -vvv db02-relay-bin.000005
 
    3)截取数据
        [root@db02 data]# mysqlbinlog --start-position=283 --stop-position=1112 db02-relay-bin.000005 > /tmp/yanshi.sql
5.将从库全备的数据与relaylog截取数据拷贝到主库
    scp /tmp/yanshi.sql 172.16.1.51:/tmp/
    scp /backup/congku.sql 172.16.1.51:/tmp/
6.将数据导入主库
    #导入前不要停掉binlog,
    mysql < /tmp/yanshi.sql
    mysql < /tmp/congku.sql
7.开启从库的sql线程
    start slave sql_thread;
 
#主库那边执行到删除的时候没关系,因为还有创建的部分,他会再次把数据创建回来

总结

MySQL 异步复制的核心特点是什么?

答:主库写入 binlog 后立即返回客户端,不等待从库同步,性能最高但存在数据丢失风险,是 MySQL 默认的复制模式。

异步复制为什么会丢失数据?如何避免?

答:主库写入 binlog 后未发送到从库就宕机,会导致数据丢失。

避免方案:

① 配置 sync_binlog=1(事务提交立即刷盘) 和 innodb_flush_log_at_trx_commit=1(InnoDB 事务日志立即刷盘);

② 升级为半同步复制;

③ 实时备份 binlog 到第三方存储。

异步复制和半同步复制的区别?

答:核心区别在于主库返回时机:异步复制主库写入 binlog 后立即返回;

半同步复制主库需等待至少一个从库接收并写入 relay log 后才返回。半同步数据安全性更高,异步性能更高。

posted @ 2026-04-11 23:30  mangolxh  阅读(44)  评论(0)    收藏  举报