当前位置:Gxlcms > 数据库问题 > MySQL之七---Mysql实现数据库主从复制、主主复制、级联复制、半同步复制及复制监控

MySQL之七---Mysql实现数据库主从复制、主主复制、级联复制、半同步复制及复制监控

时间:2021-07-01 10:21:17 帮助过:14人阅读

(1)扩展方式: Scale Up ,Scale Out

(2)MySQL的扩展

 读写分离
 复制:每个节点都有相同的数据集
 向外扩展
 二进制日志
 单向

(3)复制的功用:

 数据分布
 负载均衡读
 备份
 高可用和故障切换
 MySQL升级测试

一主多从  

技术图片

 

主从复制介绍

两台或两台以上实例,通过binlog实现最终数据同步关系;

主从复制前提(搭建过程)

 a.至少两台MySQL实例,server_id,server_uuid不同;
 b.主库要开binlog
 c.专用的复制用户和权限
 d.预同步主库数据到从库
 e.告诉从库连接\同步起点
 f.启动复制线程

主从复制搭建(Classic replication)

配置主库

  1. 安装 mysql 8.0.20 二进制包

  2. 配置二进制文件路径,server_id

 cat > /etc/my.cnf <<EOF
 [mysqld]
 user=mysql
 basedir=/usr/local/mysql
 datadir=/data/3306/data
 port=3306
 socket=/tmp/mysql.sock
 server_id=10
 log_bin=/data/3306/data/binlog
 plugin-load-add=mysql_clone.so
 clone=FORCE_PLUS_PERMANENT
 [client]
 socket=/tmp/mysql.sock
 EOF
  1. 重启MySQL

 systemctl restart mysqld
  1. 验证二进制日志,clone插件是否开启,server_id,server_uuid是否和从库不同

 select @@log_bin;
 select @@log_bin_basename;
 select @@server_id;
 select @@server_uuid;
 SELECT PLUGIN_NAME, PLUGIN_STATUS
 FROM INFORMATION_SCHEMA.PLUGINS
 WHERE PLUGIN_NAME LIKE ‘clone‘;
  1. 创建复制专用用户并授权

 create user repl@‘10.0.0.%‘ identified with mysql_native_password by  ‘123‘;
 grant replication slave on *.* to repl@‘10.0.0.%‘;
  1. 创建给予端用户并授权

 CREATE USER ‘donor_clone_user‘@‘%‘ IDENTIFIED BY ‘123‘;
 GRANT BACKUP_ADMIN on *.* to ‘donor_clone_user‘@‘%‘;
  1. 查看主状态

 show master status;

配置从库

  1. 安装 mysql 8.0.20 二进制包

  2. 配置server_id和主库不同

 cat > /etc/my.cnf <<EOF
 [mysqld]
 user=mysql
 basedir=/usr/local/mysql
 datadir=/data/3306/data
 port=3306
 socket=/tmp/mysql.sock
 server_id=20
 log_bin=/data/3306/data/binlog
 plugin-load-add=mysql_clone.so
 clone=FORCE_PLUS_PERMANENT
 [client]
 socket=/tmp/mysql.sock
 EOF
  1. 重启MySQL

 systemctl restart mysqld
  1. 验证server_id,server_uuid是否和从库不同,clone插件是否开启

 select @@server_id;
 select @@server_uuid;
 SELECT PLUGIN_NAME, PLUGIN_STATUS
 FROM INFORMATION_SCHEMA.PLUGINS
 WHERE PLUGIN_NAME LIKE ‘clone‘;
  1. 创建接受端用户并授权

 CREATE USER ‘recipient_clone_user‘@‘%‘ IDENTIFIED BY ‘123‘;
 GRANT CLONE_ADMIN on *.* to ‘recipient_clone_user‘@‘%‘;
  1. 设置主库IP:端口加入给予主机列表

SET GLOBAL clone_valid_donor_list=‘10.0.0.51:3306‘;
  1. 使用克隆用户连接新数据库

 mysql -urecipient_clone_user -p1 -h10.0.0.61
  1. 执行远程克隆

 CLONE INSTANCE FROM ‘donor_clone_user‘@‘10.0.0.51‘:3306 IDENTIFIED BY ‘123‘;
  1. 克隆完成,新数据库自动重启

  2. 使用root用户连接新数据库

 mysql -uroot -p123
  1. 查看克隆状态信息

 mysql> select * from performance_schema.clone_status\G
 *************************** 1. row ***************************
              ID: 1
             PID: 0
           STATE: Completed
      BEGIN_TIME: 2020-11-18 10:22:39.531
        END_TIME: 2020-11-18 10:22:46.824
          SOURCE: 10.0.0.51:3306
     DESTINATION: LOCAL INSTANCE
        ERROR_NO: 0
   ERROR_MESSAGE: 
     BINLOG_FILE: binlog.000021
 BINLOG_POSITION: 276
   GTID_EXECUTED: 1aa38bc6-1cbc-11eb-a6b8-000c29caebef:1-9,
 c985eb8e-2896-11eb-a6af-000c29caebef:1-3,
 d1d0b198-2899-11eb-babe-000c29caebef:1-4
 1 row in set (0.01 sec)
  1. 告诉从库连接信息,从什么位置点开始自动复制(help change master to

 CHANGE MASTER TO
   MASTER_HOST=‘10.0.0.51‘,
   MASTER_USER=‘repl‘,
   MASTER_PASSWORD=‘123‘,
   MASTER_PORT=3306,
   MASTER_LOG_FILE=‘binlog.000021‘,
   MASTER_LOG_POS=276,
   MASTER_CONNECT_RETRY=10;

注意:MASTER_LOG_FILEMASTER_LOG_POS必须和主库中show master status;查到的一致

  1. 启动复制线程

 start slave;
  1. 查看从状态

 show slave status \G

主从复制原理

主从复制线程:

 # 主库:  
   binlog 二进制日志
 # 从库 
   relaylog:中继日志,从库用来临时存储接收到的binlog
   master.info:主库相关信息(ip port user password  已经获取的binlog 位置点)
   relay-log.info:存储SQL线程回放过的日志
   三线程四文件(主库一个文件,从库三个文件。主库一个线程,从库两个线程)

主节点:

 dump Thread:为每个Slave的I/O Thread启动一个dump线程,用于向其发送binary log events

从节点:

 I/O Thread:向Master请求二进制日志事件,并保存于中继日志中
 SQL Thread:从中继日志中读取日志事件,在本地完成重放

主从复制特点:

 异步复制
 主从数据不一致比较常见

复制架构:

 Master/Slave, Master/Master, 环状复制
 一主多从
 从服务器还可以再有从服务器
 一从多主:适用于多个不同数据库
 主主

复制需要考虑二进制日志事件记录格式

 STATEMENT(5.0之前)
 ROW(5.1之后,推荐)
 MIXED

 技术图片

 

 

主从复制(Classic Replication)原理描述:异步复制

  1. 从库执行 change master to ... 时,将主库连接信息和binlog位置信息写入master.info文件或者slave_master_info表中

  2. 从库执行 start slave 时,从库启动IO线程和SQL线程

  3. IO线程读取master.info,获取主库信息连接主库

  4. 主库会生成一个DUMP线程(自动监控binlog变化),来响应从库

  5. IO线程根据master.info记录的binlog文件名和position号,请求主库DUMP最新日志

  6. DUMP线程检查主库的binlog日志,如果有新的,传送给从从库的IO线程,主库不关心投递的结果(异步)。

  7. IO线程将收到的日志存储到了TCP/IP 缓存

  8. IO线程将缓存中的数据,存储到relay-log日志文件,更新master.info文件或者slave_master_info表的binlog 文件名和postion,IO线程工作完成

  9. SQL线程读取relay-log.info文件或者slave_relay_log_info表,获取到上次执行到的db02-relay-bin的位置,作为起点,回放db02-relay-bin

  10. SQL线程回放完成之后,会更新relay-log.info文件。

  11. 回放过的db02-relay-binrelay_log_purge线程会定期删除这些日志。

注意:主库一旦有新的日志生成,dump 会发送“信号”给从库 ,IO线程再去请求

主从配置过程:参看官网

https://mariadb.com/kb/en/library/setting-up-replication/ https://dev.mysql.com/doc/refman/5.5/en/replication-configuration.html

常见报错场景:

  • 通信故障:

    • 外部网络问题(防火墙,网络不通,...)

    • 连接信息问题(ip\port\user\passwd)

      • 用户错误

      • 密码错误

       -- 报错信息:
       
      Slave_IO_Running: Connecting
       Last_IO_Errno: 1045
       Last_IO_Error: error connecting to master ‘repl1@10.0.0.51:3306‘ - retry-time: 10 retries: 2 message: Access denied for user ‘repl1‘@‘10.0.0.61‘ (using password: YES)
       -- 连接测试:
      
       [root@db01 ~]# mysql -urepl  -p123333  -h 10.0.0.51 -P 3306
       mysql: [Warning] Using a password on the command line interface can be insecure.
       ERROR 1045 (28000): Access denied for user ‘repl‘@‘10.0.0.61‘ (using password: YES)
      

       -- 处理方法:
       stop slave;
       reset slave all;
       change master to ... ;
       start slave;
       show slave status \G
      
      • 地址错误

       Slave_IO_Running: Connecting
       Last_IO_Errno: 0
       Last_IO_Error:
      
      • 端口错误

       -- 报错信息:
       Slave_IO_Running: Connecting
       Last_IO_Errno: 2003
       Last_IO_Error: error connecting to master ‘repl@10.0.0.51:3307‘ - retry-time: 10 retries: 1 message: Can‘t connect to MySQL server on ‘10.0.0.51‘ (111)
       -- 连接测试:
      
       [root@db01 opt]# mysql -urepl  -p123333  -h 10.0.0.51 -P 3307
       mysql: [Warning] Using a password on the command line interface can be insecure.
       ERROR 2003 (HY000): Can‘t connect to MySQL server on ‘10.0.0.51‘ (111)
      
      • 禁止域名解析:skip_name_resolve

    • 达到最大连接数上限

     -- 报错信息:
     Last_IO_Errno: 1040
     Last_IO_Error: error reconnecting to master ‘repl@10.0.0.51:3307‘ - retry-time: 10  retries: 7
    
     -- 连接测试:
     [root@db01 ~]# mysql -urepl -p123 -h 10.0.0.51 -P 3307 
     mysql: [Warning] Using a password on the command line interface can be insecure.
     ERROR 1040 (HY000): Too many connections
     -- 处理方法:
     set global max_connections=1024;
  • 请求二进制日志故障:

    • 主库二进制日志文件名错误或缺失

     Slave_IO_Running: No
     Last_IO_Errno: 13114
     Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 
    ‘Could not find first log file name in binary log index file‘
    • 主库二进制日志文件位置点错误

     Slave_IO_Running: No
     Last_IO_Errno: 13114
     Last_IO_Error: Got fatal error 1236 from master when reading data from binary log: 
    ‘binlog truncated in the middle of event; consider out of disk space on master; the first event ‘binlog.000021‘ at 156, the last event read from ‘/data/3306/data/binlog.000021‘ at 125,
    the last byte read from ‘/data/3306/data/binlog.000021‘ at 276.‘

    注意: 在主从复制中,禁止主库reset master;。可以选择 expire 进行定期清理主库二进制日志

  • server_id重复

 Last_IO_Errno: 13117
 Last_IO_Error: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server ids; 
these ids must be different for replication to work (or the --replicate-same-server-id 
option must be used on slave but this does not always make sense; please check the manual before using it).
 
  • server_uuid重复

 Last_IO_Errno: 1593
 Last_IO_Error: Fatal error: 
The slave I/O thread stops because master and slave have equal MySQL server UUIDs; 
these UUIDs must be different for replication to work.

SQL 线程

正常状态:

 Slave_SQL_Running: Yes
 Last_SQL_Errno: 0
 Last_SQL_Error: 

故障状态:

 Slave_SQL_Running: NO
 Last_SQL_Errno: 故障代码
 Last_SQL_Error: 故障信息

故障原因分析:

SQL线程功能:回放relay-log.info,执行里面的SQL语句。

故障现象

  • relay-log损坏,断节,找不到

  • 接收到的SQL无法执行

    • 要创建的对象,已经存在

    • 要删除或修改的对象不存在

    • 约束冲突,DML语句不符合表定义及约束

    • 版本差异,参数设定不同,比如:数据类型的差异,SQL_MODE影响

故障原因

  • chang master to ... 指定的binlog位置点不对

  • 从库被写入

  • 业务繁忙时,从库宕机了

  • 主从切换时,没有正确操作(锁定原主库+binlog写入)

  • 双主结构,没有正确使用


 Last_SQL_Error: Error ‘Can‘t create database ‘db‘;
 database exists‘ on query. 
Default database: ‘db‘. Query: ‘create database db‘

解决方案:

  1. 以主库为准

    1. 冲突操作回退回去

    2. 从库跳过错误

      1. pt-checksum/pt-sync

      2. 从库跳过指定错误代码

       vim /etc/my.cnf
       [mysqld]
       slave-skip-errors = 1032,1062,1007
       常见错误代码:
       1007: 对象已存在
       1032: 无法执行DML
       1062: 主键冲突,或约束冲突
      1. 将同步指针向下移动一个,如果多次不同步,可以重复操作。

       stop slave;
       set global sql_slave_skip_counter=1;
       start slave;
    3. 删除从库中有冲突的数据,有风险

    4. 最安全的做法就是重新构建主从

  2. 从库配置只读

 show variables like ‘%read_only%‘;
 select @@read_only;
 select @@super_read_only;
?
 -- 普通用户只读
 set @@read_only=1;
 -- 管理员用户只读
 set @@super_read_only=1;
  1. 双主结构,屏蔽多写

  2. 加中间件,读写分离。

主从延时故障分析和处理

主从延时:主库做的操作,从库很久才做。

主从延时带来的延伸问题:

  • 读写分离架构,依赖主从环境。主库作为写节点,从库作为读节点。要是过高,导致读的不及时。

  • 高可用架构,依赖主从环境。主库宕机,故障切换时,可能会丢失较多数据。


监控

时间差,主从延时的秒数(非人为)

 Seconds_Behind_Master: 0

主库日志执行位置点

 Master_Log_File: mysql-bin.000005
 Read_Master_Log_Pos: 444

从库日志执行位置点

 Relay_Log_File: db01-relay-bin.000002
 Relay_Log_Pos: 485

对比主从日志执行位置点,可以找到故障操作点,计算延时日志量


外在原因

  • 主从硬件差异

  • 主从版本差异

  • 网络问题:延时、阻塞、攻击

  • 资源耗尽

    • 大事务(尽量切割)大事务拆成多个小事务,可以有效的减少主从延时。5.7 并行事务

    • 全表扫描

    • 存储过程

    • DDL阻塞

    • ...

  • 其他原因

    • 过度追求安全:从库关闭“双一”

    • 锁冲突:RR隔离级别,锁冲突严重;调整为RC隔离级别,保证索引主从一致


主库原因

产生场景:

  1. 主库并发大量事务

  2. 从库个数多

binlog_dump 线程以事件为单元,串行传输二进制日志给从库IO,串行阻塞后续的事务(5.6 5.5),导致主从延时。


解决方案:

  • 5.6 版本:开启GTID,实现GC(group commit)机制,将多个事务redo log的刷盘动作合并,减少磁盘顺序写,提高性能。

     技术图片

     

     5.7 版本:不开启GTID,也会自动维护匿名的GTID,也能实现GC,建议开启GTID

从库原因

产生场景:

主库并发大量事务,从库默认只有一个SQL线程,串行回放relay-log中的事务,阻塞后续的事务运行,导致主从延时。


解决方案:

  1. 5.6 版本:开启GTID,加入SQL多线程的特性,但是只能针对不同库(database)下的事务进行并发回放。

  2. 5.7 版本:开始GTID,加入MTS(enhanced multi-threaded slave)技术,基于logical_clock(逻辑时钟)机制,binlog加入了seq_no机制,真正实现了基于事务级别的并发回放。


过滤复制

产生情景:

需求:master 有4个库A,B,C ,D,现在需要将其中2个库B,C单独拆分出来。

做法:单独搭建一个只有B,C库的实例,然后只复制master的B,C库,过滤掉A,D库。


主库控制

 show master status;
 # 使用白名单或黑名单控制二进制日志是否记录,不常用
 Binlog_Do_DB        # 白名单,出现的记录
 Binlog_Ignore_DB    # 黑名单,出现的不记录

从库控制

 show slave status\G
 # 在SQL线程回放流程中,加入过滤功能:库,表,通配符表的白名单和黑名单
 # 白名单:只执行白名单中列出的库或者表的中继日志
 # 黑名单:不执行黑名单中列出的库或者表的中继日志
 Replicate_Do_DB
 Replicate_Ignore_DB
 Replicate_Do_Table
 Replicate_Ignore_Table
 Replicate_Wild_Do_Table
 Replicate_Wild_Ignore_Table

在线配置:

stop slave SQL_THREAD;
 change replication filter Replicate_Do_Table=(test.t1,test.t2);
 start slave sql_thread;

永久配置:

 vim /etc/my.cnf
 [mysqld]
 replicate_do_table=test.t1
 replicate_do_table=test.t2

更改复制过滤器语句


Database-Level Replication 流程图

注意1:库级别的规则,只针对binlog_format=‘STATEMENT or MIXED‘ 注意2:binlog_format=‘ROW’,不受库级别规则限制,只受表级别规则限制。


 技术图片

 

总结

注意: 以下总结和测试,前提都是binlog-format=‘MIXED‘


  • DB level:

    • binlog-format=statement时,过滤以use DB为主(不允许跨库)

    • binlog-format=row时:过滤不以use DB为主(允许跨库)

  • binlog-format=statement or row,table level 的判断都是不以use DB为主(可以跨库的)

  • 总的流程走向:

    • 先判断 DB-level,如果 DB-level 判断完成后需要 exit,则退出。

    • 如果 DB-level 判断完成后,没有 exit,则再判断Table-level。

  • DB-level:

    • 如果有 replicate-do-db,则判断 replicate-do-db,将不会走到 replicate-ignore-db 这层。

      如果判断 replicate-do-db 符合条件,则判断 table-level。 如果不符合,则exit。

    • 如果没有 replicate-do-db,但是有 replicate-ignore-db 。

      如果判断符合replicate-ignore-db规则,则exit。不符合,则走到 table-level 层继续判断。

  • Table-level:

    • 判断逻辑顺序自上而下为:replicate-do-table -> replicate-ignore-table -> replicate-wild-do-table -> replicate-wild-ignore-table

    • 从第一个阶段(replicate-do-table)开始,如果符合replicate-do-table判断规则,则exit。

      如果不符合,则跳到下一层(replicate-ignore-table)。

      以此类推,直到最后一层(replicate-wild-ignore-table)都不符合,则最后判断是否有(replicate-do-table or replicate-wild-do-table),如果有,则 ignore & exit。如果没有,则execute & exit


说明:以下测试,均以statement格式为例。 rows模式参见原理同样可以证明。

  • 设置replicate_do_DB=A,B

 结论:A和B都没有在slave上执行。因为mysql将‘A,B‘作为一个库名。

只有库级别的规则

  • do-db

 replicate_do_DB=A
 replicate_do_DB=B
  • ignoare-db

 replicate_ignore_DB=A
 replicate_ignore_DB=B
  • do-db & ignore-db

 replicate_do_DB=A
 replicate_do_DB=B
 replicate-ignore-db=mysql
 replicate-ignore-db=test

只有表级别的规则

  • do-table

  • ignore-table

  • wild-do-table

  • wild-ignore-table

  • do-table & ignore-table

  • do-table & wild-ignore-table

  • wild-do-table & wild-ignore-table

库和表级别的规则混用

  • do-DB & do-table

 replicate_do_DB=A
 replicate_do_DB=B
 replicate-do-table=table1
 replicate-do-table=table2
  • do-DB & wild-do-table

 replicate_do_DB=A
 replicate_do_DB=B
 replicate-wild-do-table=mysql.%
 replicate-wild-do-table=test.%
  • do-DB & ignore-table

 replicate_do_DB=A
 replicate_do_DB=B
 replicate-ignore-table=table1
 replicate-ignore-table=table2
  • do-DB & wild-ignore-table

 replicate_do_DB=A
 replicate_do_DB=B
 replicate-wild-ignore-table=mysql.%
 replicate-wild-ignore-table=test.%
  • 最常见场景: db-db & do-ignore-db & wild-do-table & wild-ignore-table

 常见场景:将master上的A,B库 拆分到 新的一组机器上。
 特点:
     1) slave 不复制 master 的 mysql,test 库
     2) slave 只复制 master 的 A,B 库所有操作
 ?
 replicate-ignore-db=mysql
 replicate-ignore-db=test
 replicate-wild-ignore-table=mysql.%
 replicate-wild-ignore-table=test.%
 replicate_do_DB=A
 replicate_do_DB=B
 replicate-wild-do-table=A.%
 replicate-wild-do-table=B.%

 误区:
     1) 如果我的 default database 不是A或者B,那么接下来的操作就不会被slave 执行,然后悲剧就产生了。
     master> use C;insert into A.id values(1);
     2)所以,以上cnf配置,只适合 default database 是 A,B 的情况。
 ?
 如果要完成这种需求,应该这样配置[前提:开发没有权限登陆到mysql,test库]:
 ?
 replicate-ignore-db=mysql
 replicate-ignore-db=test
 replicate-wild-ignore-table=mysql.%
 replicate-wild-ignore-table=test.%
 replicate-wild-do-table=A.%
 replicate-wild-do-table=B.%
  • 实战: wild-do-table & ignore-table & wild-ignore-table

需求: 将老服务器上的某个库,迁移到新机器上

 old_master[库: A , B , mysql] ---->(同步) new_maser[A]

验证单库(A)复制的正确性: 规则=> slave 只复制A库,不复制B库

 Replicate_Wild_Do_Table: A.%
 Replicate_Ignore_DB: mysql
 Replicate_Wild_Ignore_Table: mysql.%

 a)use A/B; insert A.a select B.b from B ;  
--err:同步报错,slave没有B库的内容
 b) use A/B; insert A.a select B.b from A,B where A.b=B.b;   
--err:同步报错,slave没有B库的内容
 c) use mysql; insert into A.a values(‘a‘); 
--err: 同步不报错,但是老master的binlog没有在slave执行,因为Replicate_Ignore_DB: mysql,Replicate_Wild_Ignore_Table: mysql.%
 d) use 空库; insert into A.a values(‘a‘);  --ok: 可以同步复制下来
 e) use B;   insert into A.a values(‘a‘);  --ok: 可以同步复制下来

 


延时从库

产生情景:

需求:主从复制非常擅长解决物理损坏,但是没办法处理逻辑损坏,例如主库有个误删除写入的操作,正常情况下从库也会同步这个错误,怎么能避免这个情况?

做法:建立延时从库,delay(延时)从节点同步数据。可以处理逻辑损坏,但只能做备用库。

原理:对SQL线程回放流程,进行延时设置。

建议:一般企业建议3-6小时,具体看公司运维人员对于故障的反应时间


参数配置

查看延时时间

 show slave status\G
 # 延时时间,单位秒
 SQL_Delay: 0
 # 延时剩余时间,单位秒
 SQL_Remaining_Delay: NULL

查看中继日志

 show relaylog events in ‘db01-relay-bin.000002‘;
 

在线配置:

 stop slave SQL_THREAD;
 change master to master_delay = 300;
 start slave sql_thread;

故障恢复思路一

故障场景:一主一从,从库延时5分钟,主库误删1个库

故障模拟:主库操作

 create database relay charset utf8;
 use relay;
 create table t1 (id int);
 insert into t1 values(1);
 commit;
 drop database relay;

故障恢复操作:

  1. 5分钟之内,侦测到误删除操作

  2. 从库停止SQL线程:

     stop slave SQL_THREAD;
    
  3. 从库查找截取relaylog的起点和终点

    • 起点:停止SQL线程时,relay最后应用的位置

       mysql> show slave status\G
       ... ...
       Relay_Log_File: db02-relay-bin.000002
       Relay_Log_Pos: 321
       ... ...
      
    • 终点:误删除之前的Position(GTID)

       mysql> show relaylog events in ‘db02-relay-bin.000002‘;
       | Log_name             | Pos  | Event_type     | Server_id | End_log_pos | Info                                               |
       ... ...
       | m01-relay-bin.000002 |  988 | Anonymous_Gtid |         1 |        1020 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘               |
       | db01-relay-bin.000002 | 1065 | Query          |         1 |        1127 | drop database relay /* xid=81 */   
                      |
  4. 从库截取relaylog

     mysqlbinlog --start-position=321 --stop-position=988 /data/3306/data/db02-relay-bin.000002 > /tmp/relay.sql
    
  5. 从库确认截取文件

     tail -10 /tmp/relay.sql
    
  6. 从库恢复截取的日志

     source /tmp/relay.sql
    
  7. 从库身份解除,替代主库工作

     stop slave;
     reset slave all;
    
  8. 业务改用从库


故障恢复思路二

  1. 5分钟之内,侦测到误删除操作

  2. 从库停止SQL线程:

     stop slave SQL_THREAD;
    
  3. 关闭延迟从库

     CHANGE MASTER TO MASTER_DELAY = 0;
    
  4. 从库查询误删除之前的Position(GTID)

     mysql> show slave status\G
     ... ...
     Relay_Log_File: db02-relay-bin.000002
     ... ...
     mysql> show relaylog events in ‘db02-relay-bin.000002‘;
     | Log_name             | Pos  | Event_type     | Server_id | End_log_pos | Info                                               |
     ... ...
     | m01-relay-bin.000002 |  988 | Anonymous_Gtid |         1 |        1020 | SET @@SESSION.GTID_NEXT= ‘ANONYMOUS‘               |
     | db01-relay-bin.000002 | 1065 | Query          |         1 |        1127 | drop database relay /* xid=81 */     
                  |
  5. 从库SQL线程自动回放,直到DROP操作之前。

    • binlog方式UNTIL

     START SLAVE SQL_THREAD UNTIL RELAY_LOG_FILE = ‘db01-relay-bin.000002‘, RELAY_LOG_POS = 988 ;
    
    • GTID方式UNTIL

     START SLAVE UNTIL SQL_BEFORE_GTIDS = "1aa38bc6-1cbc-11eb-a6b8-000c29caebef:4";
    
  6. 从库身份解除,替代主库工作

     stop slave;
     reset slave all;
    
  7. 业务改用从库


半同步复制

从 MYSQL 5.5 开始,支持半同步复制(Semi synchronous Replication),一定程度上保证提交的事务已经传给了至少一个备库。解决主从数据不一致问题,提供一般一致性。可使用多从库提高ACK接收率。

之前版本的MySQL Replication都是异步(asynchronous)的,主库在执行完一些事务后,是不会管备库的进度的。如果备库不幸落后,而更不幸的是主库此时又出现Crash(例如宕机),这时备库中的数据就是不完整的。如果主库发生故障,此时我们无法使用备库来继续提供数据一致的服务了。

5.5 出现概念,但是不建议使用,性能太差 5.6 出现 group commit 组提交功能,来提升开启半同步复制的性能 5.7 更加完善了,在 group commit 基础上出现了MGR 5.7 增强半同步复制的新特性:after commitafter sync


半同步复制工作原理的变化

  1. 主库执行新的事务,commit时阻塞

  2. 更新 show master status 信息,触发一个信号给 binlog dump

  3. binlog dump 通知从库日志更新了

  4. 从库IO线程请求新的二进制日志事件

  5. 主库通过binlog dump线程,传送新的二进制日志事件,给从库IO线程

  6. 从库IO线程接收到binlog,当日志写入到磁盘上的relaylog文件时,给主库ACK_receiver线程响应

  7. ACK_receiver 线程触发一个事件,告诉主库commit可以成功了

  8. 如果ACK_receiver 等待,达到了预设的超时时间还没有收到响应,半同步复制会切换为原始的异步复制


半同步复制配置

配置主库

在线配置:

 # 查看是否有动态支持
 show global variables like ‘have_dynamic_loading‘;

 # 安装自带插件
 INSTALL PLUGIN rpl_semi_sync_master SONAME‘semisync_master.so‘;

 # 启动插件

人气教程排行