好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

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

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

(2)MySQL的扩展

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

(3)复制的功用:

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

一主多从  

 

主从复制介绍

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

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

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

主从复制搭建(Classic replication)

配置主库

安装 mysql 8.0.20 二进制包

配置二进制文件路径,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

重启MySQL

 systemctl restart mysqld

验证二进制日志,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‘;

创建复制专用用户并授权

 create user repl@‘10.0.0.%‘ identified with mysql_native_password by  ‘123‘;
 grant replication slave on *.* to repl@‘10.0.0.%‘;

创建给予端用户并授权

 CREATE USER ‘donor_clone_user‘@‘%‘ IDENTIFIED BY ‘123‘;
 GRANT BACKUP_ADMIN on *.* to ‘donor_clone_user‘@‘%‘;

查看主状态

 show master status;

配置从库

安装 mysql 8.0.20 二进制包

配置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

重启MySQL

 systemctl restart mysqld

验证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‘;

创建接受端用户并授权

 CREATE USER ‘recipient_clone_user‘@‘%‘ IDENTIFIED BY ‘123‘;
 GRANT CLONE_ADMIN on *.* to ‘recipient_clone_user‘@‘%‘;

设置主库IP:端口加入给予主机列表

SET GLOBAL clone_valid_donor_list=‘10.0.0.51:3306‘;

使用克隆用户连接新数据库

 mysql -urecipient_clone_user -p1 -h10.0.0.61

执行远程克隆

 CLONE INSTANCE FROM ‘donor_clone_user‘@‘10.0.0.51‘:3306 IDENTIFIED BY ‘123‘;

克隆完成,新数据库自动重启

使用root用户连接新数据库

 mysql -uroot -p123

查看克隆状态信息

 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)

告诉从库连接信息,从什么位置点开始自动复制( 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_FILE 和 MASTER_LOG_POS 必须和主库中 show master status; 查到的一致

启动复制线程

 start slave;

查看从状态

 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)原理描述:异步复制

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

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

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

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

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

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

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

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

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

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

回放过的 db02-relay-bin , relay_log_purge 线程会定期删除这些日志。

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

主从配置过程:参看官网

https://mariadb测试数据/kb/en/library/setting-up-replication/ https://dev.mysql测试数据/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‘

解决方案:

以主库为准

冲突操作回退回去

从库跳过错误

pt-checksum / pt-sync

从库跳过指定错误代码

   vim /etc/my.cnf
  [mysqld]
  slave-skip-errors = 1032,1062,1007
  常见错误代码:
  1007: 对象已存在
  1032: 无法执行 DML
  1062: 主键冲突,或约束冲突

将同步指针向下移动一个,如果多次不同步,可以重复操作。

  stop  slave;
  set global sql_slave_skip_counter= 1;
  start slave;

删除从库中有冲突的数据,有风险

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

从库配置只读

 show variables like ‘%read_only%‘;
 select @@read_only;
 select @@super_read_only;
            ?
  -- 普通用户只读
  set @@read_only= 1;
  -- 管理员用户只读
  set @@super_read_only= 1;

双主结构,屏蔽多写

加中间件,读写分离。

主从延时故障分析和处理

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

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

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

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

监控

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

 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隔离级别,保证索引主从一致

主库原因

产生场景:

主库并发大量事务

从库个数多

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

解决方案:

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

 

 

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

从库原因

产生场景:

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

解决方案:

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

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;

故障恢复操作:

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

从库停止SQL线程:

 stop slave SQL_THREAD;

从库查找截取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 */   
                                         |                         

从库截取relaylog

 mysqlbinlog --start-position=321 --stop-position=988 /data/3306/data/db02-relay-bin.000002 > /tmp/relay.sql

从库确认截取文件

 tail -10 /tmp/relay.sql

从库恢复截取的日志

 source /tmp/relay.sql

从库身份解除,替代主库工作

 stop slave;
 reset slave all;

业务改用从库

故障恢复思路二

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

从库停止SQL线程:

 stop slave SQL_THREAD;

关闭延迟从库

 CHANGE MASTER TO MASTER_DELAY = 0;

从库查询误删除之前的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 */     
                                                |                                  

从库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";

从库身份解除,替代主库工作

 stop slave;
 reset slave all;

业务改用从库

半同步复制

从 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 commit ; after sync ;

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

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

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

binlog dump 通知从库日志更新了

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

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

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

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

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

半同步复制配置

配置主库

在线配置:

   # 查看是否有动态支持
 show global variables like ‘have_dynamic_loading‘;
        
  # 安装自带插件
 INSTALL PLUGIN rpl_semi_sync_master SONAME‘semisync_master.so‘;
               
  # 启动插件

查看更多关于MySQL之七---Mysql实现数据库主从复制、主主复制、级联复制、半同步复制及复制监控的详细内容...

  阅读:36次