https://shuen.blog.csdn.net/article/details/108712516?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_aa&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7ECTRLIST%7Edefault-1.pc_relevant_aa&utm_relevant_index=1

Mysql主从复制 

1.)普通主从复制:

  普通主从复制主要是基于二进制日志文件位置的复制,因此主必须启动二进制日志记录并建立唯一的服务器ID,复制组中的每个服务器都必须配置唯一的服务器ID。如果您省略server-id(或者明确地将其设置为其默认值0),则主设备将拒绝来自从设备的任何连接。 
2.) GTID 主从: 

(1.)基本概念

  MySQL 5.6 的新特性之一,全局事务标识符(GTID)是创建的唯一标识符,并与在源(主)服务器上提交的每个事务相关联。此标识符不但是唯一的,而且在给定复制设置中的所有服务器上都是唯一的。所有交易和所有GTID之间都有一对一的映射关系 。它由服务器ID以及事务ID组合而成。这个全局事务ID不仅仅在原始服务器上唯一,在所有存在主从关系 的mysql服务器上也是唯一的。正是因为这样一个特性使得mysql的主从复制变得更加简单,以及数据库一致性更可靠。一个GTID在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

  一个GTID被表示为一对坐标,用冒号(:)分隔,如下所示:GTID = source_id:transaction_id,source_id标识的源服务器。通常情况下,服务器 server_uuid用于这个目的。这transaction_id是一个序列号,由在此服务器上提交事务的顺序决定 .

3E11FA47-71CA-11E1-9E33-C80AA9429562:23

在传统的主从复制slave端,binlog是不用开启的,但是在GTID中slave端的binlog是必须开启的,目的是记录执行过的GTID(强制)。GTID用来代替classic的复制方法,不在使用binlog+pos开启复制。而是使用master_auto_postion=1的方式自动匹配GTID断点进行复制。

  mysql的主从复制是十分经典的一个应用,但是主从之间总会有数据一致性(data consistency )的问题,一般情况从库会落后主库几个小时,而且在传统一主多从(mysql5.6之前)的模型中当master down掉后,我们不只是需要将一个slave提成master就可以,还要将其他slave的同步目的地从以前的master改成现在master,而且bin-log的序号和偏移量也要去查看,这是十分不方便和耗时的,但mysql5.6引入gtid之后解决了这个问题。

红色代表GTID,绿色代表传统主从:

优缺点

优点

1)GTID相对于行复制数据安全性更高,故障切换更简单。

2) 简单的实现 failover,不用以前那样在需要找 log_file 和 log_pos。

3) 更简单的搭建主从复制,确保每个事务只会被执行一次。

4) 比传统的复制更加安全,一个 GTID 在一个服务器上只执行一次,避免重复执行导致数据混乱或者主从不一致。

5)GTID是连续的没有空洞的,保证数据的一致性,零丢失

6)GTID 用来代替classic的复制方法,不再使用 binlog+pos 开启复制。而是使用 master_auto_postion=1 的方式自动匹配 GTID 断点进行复制。

7) GTID 的引入,让每一个事务在集群事务的海洋中有了秩序,使得 DBA 在运维中做集群变迁时更加方便

8) 根据 GTID 可以快速的确定事务最初是在哪个实例上提交的。

缺点

1)主从库的表存储引擎必须是一致的

主从库的表存储引擎不一致,就会导致数据不一致。如果主从库的存储引擎不一致,例如一个是事务存储引擎,一个是非事务存储引擎,则会导致事务和 GTID 之间一对一的关系被破坏,结果就会导致基于 GTID 的复制不能正确运行;

master:对一个innodb表做一个多sql更新的事物,效果是产生一个GTID。
slave:假设对应的表是MYISAM引擎,执行这个GTID的第一个语句后就会报错,因为非事务引擎一个sql就是一个事务。

当从库报错时简单的stop slave; start slave;就能够忽略错误。但是这个时候主从的一致性已经出现问题,需要手工的把slave差的数据补上,这里要将引擎调整为一样的,slave也改为事务引擎。

2)不允许一个SQL同时更新一个事务引擎和非事务引擎的表

事务中混合多个存储引擎,就会产生多个 GTID。当使用 GTID 时,如果在同一个事务中,更新包括了非事务引擎(如 MyISAM)和事务引擎(如 InnoDB)表的操作,就会导致多个 GTID 分配给了同一个事务。

3)在一个复制组中,必须要求统一开启GTID或是关闭GTID;

4)不支持create table….select 语句复制(主库直接报错);(在Mysql 8版本中已经解决了)。

create table xxx as select的语句,其实会被拆分为两部分,create语句和insert语句,但是如果想一次搞定,MySQL会抛出如下的错误。
ERROR 1786 (HY000): Statement violates GTID consistency: CREATE TABLE ... SELECT.
create table xxx as select 的方式可以拆分成两部分,如下。
create table xxxx like data_mgr;insert into xxxx select *from data_mgr;

5)对于create temporary table 和 drop temporary table语句不支持;(Mysql5.7版本开始支持)

使用GTID复制模式时,不支持create temporary table 和 drop temporary table。但是在autocommit=1的情况下可以创建临时表,Master端创建临时表不产生GTID信息,所以不会同步到slave,但是在删除临时表的时候会产生GTID会导致,主从中断.

6)不支持sal_slave_skip_counter.

mysql在主从复制时如果要跳过报错,可以采取以下方式跳过SQL(event)组成的事务,但GTID不支持以下方式。
set global SQL_SLAVE_SKIP_COUNTER=1;start slave sql_thread;

GTID 复制原理

1) 当一个事务在主库端执行并提交时,产生 GTID,一同记录到 binlog 日志中。
2) binlog 传输到 slave,并存储到 slave 的 relaylog 后,读取这个 GTID 的这个值设置 gtid_next 变量,即告诉 Slave,下一个要执行的 GTID 值。
3) sql 线程从 relay log 中获取 GTID,然后对比 slave 端的 binlog 是否有该 GTID。
4) 如果有记录,说明该 GTID 的事务已经执行,slave 会忽略。
5) 如果没有记录,slave 就会执行该 GTID 事务,并记录该 GTID 到自身的 binlog;
6) 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

配置

 
  1. [mysqld]
    
    #GTID:
    
    server_id=1 #服务器id
    
    gtid_mode=on #开启gtid模式
    
    log_slave_updates ## 表示即可以当从也可以当主
    
    enforce_gtid_consistency=on #强制gtid一致性,开启后对于特定create table不被支持
    
    
    #binlog
    
    log_bin=master-binlog#log-bin=/data/mysql/mysql-bin.log    //binlog日志文件,(文件名如果是绝对路径,必须指定索引文件)#log_bin_index =    /var/lib/mysql/mysql-bin.index     //是binlog文件的索引文件,这个文件管理了所有的binlog文件的目录log-slave-updates=1 binlog_format=row #binlog日志格式,强烈建议,其他格式可能造成数据不一致expire_logs_days=7            //binlog过期清理时间
    
    
    #relay logskip_slave_start=1

参考: https://bbs.wwwseo.net/seo116/a10089/

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐