目录

1、基于位点的主备切换

2、GTID

GTID实例:


一主多重的切换正确性:

1、基于位点的主备切换

通常情况下,在切换任务的时候,要先主动跳过这些错误,有两种常用的方法:

1、主动跳过一个事物,跳过的命令的写法是:

set global sql_slave_skip_counter=1;

start slave;

因为切换过程中,可能会不止重复执行一个事物,所以需要在从库持续观察,每次碰到这些错误就停下来,执行一次跳过命令,直到不再出现停下来的情况,以此来跳过可能涉及的所有事务。

2、通过设置slave_skip_errors参数,直接设置跳过指定的错误:

在执行主备切换时,有这么两类错误,是经常会遇到的:

1062 错误是插入数据时唯一键冲突;

1032错误是删除数据时找不到行。

因此,可以把slave_skip_errors设置为“1032,1062”,这样中间碰到这两个错误时就直接跳过

 


2、GTID

通过sql_slave_skip_counter跳过事务和通过slave_skip_errors 忽略错误的方法,虽然都最终可以建立从库B和主库A'的主备关系,但这两种操作都很复杂,而且容易出错,所以MySQL5.6版本引入了GTID,彻底解决了这个困难。

GTID的全程是Global Transaction Identifier,也就是全局事务ID,是一个事务在提交的时候生成的,是这个事务的唯一标识。它由两部分组成,格式是:GTID=server_uuid:gno.

其中:server_uuid是一个实例第一次启动时自动生成的,是一个全局唯一的值;

gno是一个整数,初始值是1,每次提交事务的时候分配给这个事务,并加1.

在MySQL的官方文档里,GTID格式是这么定义的:

GTID=source_id:transaction_id

GTID模式的启动:在启动一个MySQL实例的时候,加上参数gtid_mode=on 和enforce_gtid_consistency=on。

在GTID模式下,每个事务都会跟一个GTID——对应。这个GTID有两种生成方式,而使用哪种方式取决于session变量gtid_next的值。

1、如果gtid_next=automatic,代表使用默认值。这时,MySQL就会把server_uuid:gno分配给这个事务   。

    a、记录binlog的时候,先记录一行 SET @@SESSION.GTID_NEXT='server_uuid:gno';

    b、把这个GTID加入本实例的GTID集合。

2、如果gtid_next是一个指定的GTID的值,比如通过set gtid_next='current_gtid'指定为current_gtid,那么就有两种可能:

    a、如果current_gtid已经存在于实例的GTID集合中,接下来执行的这个事务会直接被系统忽略;

    b、如果current_gtid没有存在于实例的GTID集合中,就将这个current_gtid分配给接下来要执行的事务,也就是说系统不需要给这个事务生成新的GTID,因此gno也不用加1

GTID实例:

CREATE TABLE `t` (

  `id` int(11) NOT NULL,

  `c` int(11) DEFAULT NULL,

  PRIMARY KEY (`id`)

) ENGINE=InnoDB;

insert into t values(1,1);

假设,现在这个实例X是另外一个实例Y的从库,并且此时在实例Y上执行了下面这条语句:

insert into t values(1,1);

并且,这条语句在实例Y上的GTID是:aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10.

那么,实例X作为Y的从库,就要同步这个事务过来执行,显然会出现主键冲突,导致实例X的同步线程停止。

处理方法就是,可以执行下面的这个语句序列:

set gtid_next='aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10'; 

begin; commit; 

set gtid_next=automatic; 

start slave;   

其中,前三条语句的作用,是通过提交一个空事务,把这个GTID加到实例X的GTID集合中。这样,再执行start slave命令让同步县城执行起来的时候,虽然实例X上还是会继续执行实例Y传过来的事务,但是由于'aaaaaaaa-cccc-dddd-eeee-ffffffffffff:10'已经存在于实例X的GTID集合中了,所以实例X就会直接跳过这个事务,就不会再出现主键冲突的错误。

在上面的这个语句序列中,start slave命令之前还有一句 set gtid_next=automatic。这句话的作用是“恢复GTID的默认分配行为”,也就是说如果之后有新的事务再执行,就还是按照原来的分配方式,继续分配gno=3.