Mysql主从复制的三种同步方式和半同步复制配置(在你之后,人人都像你,人人都不是你。)

时间:2025-03-28 07:45:17

文章目录

  • 一、MySQL主从复制的三种同步模式
    • 1.异步复制(Asynchronous replication)
    • 2.全同步复制(Fully synchronous replication)
    • 3.半同步复制(Semisynchronous replication)
  • 二、半同步复制配置
  • 三、半同步复制转为异步复制的情况
  • 四、使用半同步复制注意点
    • 1.在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。
    • 5.7极大的提升了半同步复制的性能。
  • 五、主从复制延迟的原因以及解决方法
    • 原因
    • 解决方法
  • 主从复制不一致出现的原因以及怎么处理
    • 原因
      • 1、网络的延迟
      • 2、主从两台机器的负载不一致
      • 3、max_allowed_packet设置不一致
      • 4、自增键不一致
      • 5、同步参数设置问题
      • 6、自身bug
      • 7、版本不一致
    • 处理方法
      • 1、手动执行同步+忽略错误(在业务不保证数据强一致性的情况下,可以选择忽略)
    • 2、手动执行同步+手动更正

一、MySQL主从复制的三种同步模式

1.异步复制(Asynchronous replication)

MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题:主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

2.全同步复制(Fully synchronous replication)

指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

3.半同步复制(Semisynchronous replication)

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

二、半同步复制配置

主数据库配置

vim /etc/                
 
#在 [mysqld] 区域添加下面内容
......
#加载mysql半同步复制的插件
plugin-load=rpl_semi_sync_master=semisync_master.so       
#或者设置为"1",即开启半同步复制功能     
rpl_semi_sync_master_enabled=ON        
#超时时间为1000ms,即1s                        
rpl-semi-sync-master-timeout=1000                    
 
#重启服务
systemctl restart mysqld        

从数据库配置

vim /etc/    
 
......
#这是是slave
plugin-load=rpl_semi_sync_slave=semisync_slave.so
rpl_semi_sync_slave_enabled=ON
 
systemctl restart mysqld

查看半同步是否在运行

#主数据库执行
show status like 'Rpl_semi_sync_master_status';
show variables like 'rpl_semi_sync_master_timeout';
#从数据库执行(此时可能还是OFF状态,需要在下一步重启IO线程后,从库半同步状态才会为ON)
show status like 'Rpl_semi_sync_slave_status';
 
#重启从数据库上的IO线程
STOP SLAVE IO_THREAD;
START SLAVE IO_THREAD;
 
#在主库查询半同步状态
show status like '%Rpl_semi%';    

Rpl_semi_sync_master_clients #半同步复制客户端的个数
Rpl_semi_sync_master_net_avg_wait_time #平均等待时间(默认毫秒)
Rpl_semi_sync_master_net_wait_time #总共等待时间
Rpl_semi_sync_master_net_waits #等待次数
Rpl_semi_sync_master_no_times #关闭半同步复制的次数
Rpl_semi_sync_master_no_tx #表示没有成功接收slave提交的次数
Rpl_semi_sync_master_status #表示当前是异步模式还是半同步模式,on为半同步
Rpl_semi_sync_master_timefunc_failures #调用时间函数失败的次数
Rpl_semi_sync_master_tx_avg_wait_time #事物的平均传输时间
Rpl_semi_sync_master_tx_wait_time #事物的总共传输时间
Rpl_semi_sync_master_tx_waits #事物等待次数
Rpl_semi_sync_master_wait_pos_backtraverse #可以理解为"后来的先到了,而先来的还没有到的次数"
Rpl_semi_sync_master_wait_sessions #当前有多少个session因为slave的回复而造成等待
Rpl_semi_sync_master_yes_tx #成功接受到slave事物回复的次数

三、半同步复制转为异步复制的情况

当半同步复制发生超时(由rpl_semi_sync_master_timeout参数控制,默认为10000ms,即10s),会暂时关闭半同步复制,转而使用异步复制,也就是会自动降为异步工作。

当 master dump 线程发送完一个事务的所有事件之后,如果在 rpl_semi_sync_master_timeout 内,收到了从库的响应, 则主从又重新恢复为半同步复制。

四、使用半同步复制注意点

1.在一主多从的架构中,如果要开启半同步复制,并不要求所有的从都是半同步复制。

5.7极大的提升了半同步复制的性能。

5.6 版本的半同步复制,dump thread 承担了两份不同且又十分频繁的任务:传送binlog 给 slave ,还需要等待 slave 反馈信息,而且这两个任务是串行的,dump thread 必须等待 slave 返回之后才会传送下一个 events 事务。dump thread 已然成为整个半同步提高性能的瓶颈。在高并发业务场景下,这样的机制会影响数据库整体的系统吞吐量(TPS)。
5.7 版本的半同步复制中,独立出一个 ack collector thread ,专门用于接收 slave 的反馈信息。这样 master 上有两个线程独立工作,可以同时发送 binlog 到 slave ,和接收 slave 的反馈。

五、主从复制延迟的原因以及解决方法

原因

1、master服务器高并发,形成大量事务
2、网络延迟
3、主从硬件设备导致
cpu主频、内存io、硬盘io
4、是同步复制、而不是异步复制

解决方法

1、从库优化Mysql参数。比如增大innodb_buffer_pool_size,让更多操作在Mysql内存中完成,减少磁盘操作。
2、主从服务器在同一个机房
3、从库使用高性能主机。包括cpu强悍、内存加大。避免使用虚拟云主机,使用物理主机,这样提升了i/o方面性。从库使用SSD磁盘。

主从复制不一致出现的原因以及怎么处理

原因

1、网络的延迟

由于mysql主从复制是基于binlog的一种异步复制通过网络传送binlog文件,理所当然网络延迟是主从不同步的绝大多数的原因,特别是跨机房的数据同步出现这种几率非常的大,所以做读写分离,注意从业务层进行前期设计。

2、主从两台机器的负载不一致

由于mysql主从复制是主数据库上面启动1个io线程,而从上面启动1个sql线程和1个io线程,当中任何一台机器的负载很高,忙不过来,导致其中的任何一个线程出现资源不足,都将出现主从不一致的情况。

3、max_allowed_packet设置不一致

主数据库上面设置的max_allowed_packet比从数据库大,当一个大的sql语句,能在主数据库上面执行完毕,从数据库上面设置过小,无法执行,导致的主从不一致。

4、自增键不一致

key自增键开始的键值跟自增步长设置不一致引起的主从不一致。

5、同步参数设置问题

mysql异常宕机情况下,如果未设置sync_binlog=1或者innodb_flush_log_at_trx_commit=1很有可能出现binlog或者relaylog文件出现损坏,导致主从不一致。

6、自身bug

mysql本身的bug引起的主从不同步,一般不会

7、版本不一致

特别是高版本是主,低版本为从的情况下,主数据库上面支持的功能,从数据库上面不支持该功能的情况。

处理方法

1、手动执行同步+忽略错误(在业务不保证数据强一致性的情况下,可以选择忽略)

(1)先进入主库,进行锁表,防止数据写入

mysql> flush tables with read lock;
mysql> show master status

(2)数据导出备份然后倒入从库

mysqldump -uroot -p --lock-all-tables --flush-logs db_name > /data/

(3)登录从库停止slave从节点

stop slave;

(4)倒入数据

mysql -u root -p db_name < /temp/
或mysql> source /temp/

(5)配置重新主从同步

2、手动执行同步+手动更正

前7步同上;
通过第7步的报错位置,在主库执行:
mysqlbinlog -v --stop-position=xxx ./data/ > ./
cat ./ |awk ‘/end_log_pos xxx/ {print NR}’
根据上面的NR行数,查看附近的行,定位数据不一致的地方,后续手动补全
cat ./ |awk ‘NRxxx-50,NRxxx+50’|grep -i update -A 200|grep xxxx -B 200|less
找到数据位置,@1表第一个字段值;其中@1 @2 @3…分别对应表的列名
或:
比如,报错位置 end_log_pos 440267874。可利用mysqlbinlog工具找出440267874的事件
/usr/local/mysql-5.6.30/bin/mysqlbinlog --base64-output=decode-rows -vv mysql-bin.000003 |grep -A 20 ‘440267874’
或者/usr/local/mysql-5.6.30/bin/mysqlbinlog --base64-output=decode-rows -vv mysql-bin.000003 --stop-position=440267874 | tail -20
或者usr/local/mysql-5.6.30/bin/mysqlbinlog --base64-output=decode-rows -vv mysql-bin.000003 >
主库创建临时表:
Create table xxl_job_temp like xxl_job_log_report;
将该段数据写入临时表导出导入到备库;
start slave;
show slave status\G

结果说明

Slave_IO_Running: 该参数可作为io_thread的监控项,Yes表示io_thread的和主库连接正常并能实施复制工作,No则说明与主库通讯异常,多数情况是由主从间网络引起的问题;
Slave_SQL_Running: 该参数代表sql_thread是否正常,具体就是语句是否执行通过,常会遇到主键重复或是某个表不存在。
Seconds_Behind_Master:是通过比较sql_thread执行的event的timestamp和io_thread复制好的event的timestamp(简写为ts)进行比较,而得到的这么一个差值;NULL—表示io_thread或是sql_thread有任何一个发生故障,也就是该线程的Running状态是No,而非Yes。0 — 该值为零,是我们极为渴望看到的情况,表示主从复制良好,可以认为lag不存在。正值 — 表示主从已经出现延时,数字越大表示从库落后主库越多。负值 — 几乎很少见,我只是听一些资深的DBA说见过,其实,这是一个BUG值,该参数是不支持负值的,也就是不应该出现。