【MySQL】基于GTID的复制(后包含5.7复制建议开启的参数)

一、GTID(Global Transaction Identifieds)

  1. GTID从MySQL 5.6.2版本开始支持,并在5.6.10版本之后开始完善,所以在其之间的版本并不推荐使用。
  2. GTID分为两个部分,一部分是服务的uuid,保存在MySQL数据目录的auto.cnf文件中,这个文件不能删除,非常重要,这部分是不会变的。而另一部分就是事务的ID,会随着事务的增加而递增。
    GTID:724afcc2-29d6-11e4-9902-000c290c0121:1-362
    UUID:724afcc2-29d6-11e4-9902-000c290c0121
    transactionId:1-362
    官方说明:GTID = source_id:transaction_id
    在整个复制结构中,GTID是不会变化的,几时在多个连环主从中也不会变,例如:ServerA --->ServerB ---->ServerC
    GTID从在ServerA ,ServerB,ServerC 中都是一样的。

二、GTID工作原理

  1. master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。
  2. slave端的i/o 线程将变更的binlog,写入到本地的relay log中。
  3. sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。
  4. 如果有记录,说明该GTID的事务已经执行,slave会忽略。
  5. 如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。
  6. 在解析过程中会判断是否有主键,如果没有就用二级索引,如果没有就用全部扫描。

三、GTID特点

  1. 一个事务对应一个唯一ID,一个GTID在一个服务器上只会执行一次
  2. GTID是用来代替传统复制的方法,GTID复制与普通复制模式的最大不同就是不需要指定二进制文件名和位置
  3. 减少手工干预和降低服务故障时间,当主机挂了之后通过软件从众多的备机中提升一台备机为主机

四、故障处理原理

那么GTID复制是怎么实现自动同步,自动对应位置的呢?
例如:ServerC <-----ServerA ----> ServerB
主机ServerA
备机:ServerB,ServerC


上图的意思是:

Server1(Master)崩溃,根据从上show slave status获得Master_log_File/Read_Master_Log_Pos的值,Server2(Slave)已经跟上了主,Server3(Slave)没有跟上主。这时要是把Server2提升为主,Server3变成Server2的从。这时在Server3上执行change的时候需要做一些计算,这里就不做说明了,相对来说是比较麻烦的。

这个问题在5.6的GTID出现后,就显得非常的简单。由于同一事务的GTID在所有节点上的值一致,那么根据Server3当前停止点的GTID就能定位到Server2上的GTID。甚至由于MASTER_AUTO_POSITION功能的出现,我们都不需要知道GTID的具体值,直接使用CHANGE MASTER TO MASTER_HOST='xxx', MASTER_AUTO_POSITION命令就可以直接完成failover的工作。

原理:

当ServerC链接ServerB 之后,首先在自己的二进制文件中找到从ServerA 传过来的最新的GTID,然后将这个GTID 发送到ServerB ,ServerB 获得这个GTID之后,就开始从这个GTID的下一个GTID
开始发送事务给ServerC。这种自我寻找复制位置的模式减少事务丢失的可能性以及故障恢复的时间。
按照另一种说法就是:从服务器连接到主服务器之后,把自己执行过的GTID(Executed_Gtid_Set)<SQL线程> 、获取到的GTID(Retrieved_Gtid_Set)<IO线程>发给主服务器,主服务器把从服务器缺少的GTID及对应的transactions发过去补全即可。当主服务器挂掉的时候,找出同步最成功的那台从服务器,直接把它提升为主即可。如果硬要指定某一台不是最新的从服务器提升为主, 先change到同步最成功的那台从服务器, 等把GTID全部补全了,就可以把它提升为主了。

五、GTID的限制

  1. 不支持非事务引擎
  2. 不支持create table ... select 语句复制(主库直接报错)
    原理:( 会生成两个sql,一个是DDL创建表SQL,一个是insert into 插入数据的sql。
    由于DDL会导致自动提交,所以这个sql至少需要两个GTID,但是GTID模式下,只能给这个sql生成一个GTID )
  3. 不允许一个SQL同时更新一个事务引擎表和非事务引擎表
  4. 在一个复制组中,必须要求统一开启GTID或者是关闭GTID
  5. 开启GTID需要重启(5.7除外)
  6. 开启GTID后,就不再使用原来的传统复制方式
  7. 对于create temporary table 和 drop temporary table语句不支持
  8. 不支持sql_slave_skip_counter
  9. 从传统复制模式转为GTID模式比较麻烦(不建议转换,如需转换,建议重新搭建)

六、引入GTID的意义

  1. 因为清楚了GTID的格式,所以通过UUID可以知道这个事务在哪个实例上提交的。
  2. 通过GTID可以极方便的进行复制结构上的故障转移,新主设置,参考上面故障处理原理。

七、复制环境搭建

1、从支持GTID后,MySQL添加了部分参数

mysql> show variables like '%gtid%';   
+---------------------------------+-----------+   
| Variable_name                  | Value      |   
+---------------------------------+-----------+   
| binlog_gtid_simple_recovery     | OFF       |   
| enforce_gtid_consistency        | OFF       |  
| gtid_deployment_step            | OFF       |  
| gtid_executed                   |           |  
| gtid_mode                       | OFF       |  
| gtid_next                       | AUTOMATIC |  
| gtid_owned                      |           |  
| gtid_purged                     |           |  
| simplified_binlog_gtid_recovery | OFF       |  
+---------------------------------+-----------+

2、主要的搭建方法与传统的搭建方式基本没什么区别,配置文件需添加以下参数

server_id = 249
log_bin = mysql-bin
gtid_mode = on
enforce_gtid_consistency = 1
log_slave_updates = 1
binlog_format = row #必须是row

这需要注意的是,gtid模式一定要开启gtid_mode、enforce_gtid_consistency和log_slave_updates 这三个参数,任意一个不开启都会报错

错误如下:

6512 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 or UPGRADE_STEP_2 requires --log-bin and --log-slave-updates 6512 [ERROR] Aborting 9860 [ERROR] --gtid-mode=ON or UPGRADE_STEP_1 requires --enforce-gtid-consistency 9860 [ERROR] Aborting

3、此时,我们可以查看数据库的uuid:

mysql>  select  @@server_uuid;   
+--------------------------------------+  
|  @@server_uuid                       |  
+--------------------------------------+  
| 4e659069-3cd8-11e5-9a49-001c4270714e |  
+--------------------------------------+

4、然后,我们需要在从库(备份库)上change来切换/设置它的主库

这里需要注意的是:

不使用gtid的change的方法:

mysql> change master to  master_host='127.0.0.1',master_user='rep',master_password='rep',master_log_file='mysql-bin3306.000001',master_log_pos=151,/*master_auto_position=1*/;

如果还是按照传统的方式来change的话会报错:

ERROR 1776 (HY000): Parameters MASTER_LOG_FILE, MASTER_LOG_POS, RELAY_LOG_FILE and RELAY_LOG_POS cannot be set when MASTER_AUTO_POSITION is active.

所以此时,我们需要的是使用master_auto_position这个参数去代替MASTER_LOG_FILE及MASTER_LOG_POS

语句如下:

mysql> change master to  master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3306,master_auto_position=1;

如果从库之前有过当主从的情况,或者不是新搭建环境的情况,那么还需要执行reset master语句来重置一下master

5、之后执行start slave来开启主从复制即可。

6、验证,在主库上查看进程可看到如下情况:

mysql> show processlist\G;  
***************************  1. row ***************************  
Id: 38  
User: rep  
Host: localhost:52321  
db: NULL  
Command: Binlog Dump GTID #通过GTID复制  
Time: 48  
State: Master has sent all binlog to slave; waiting for binlog to be updated  
Info: NULL  
Rows_sent: 0  
Rows_examined: 0

八、测试

1、测试复制的故障转移

模拟服务器A(master)挂掉,现在需要将服务器B或者服务器C设置为主,而另一个设置为从

1.1

首先使用show slave status查看服务器B和服务器C的进度

服务器B:

Master_Log_File: mysql-bin3306.000002  
Read_Master_Log_Pos: 4156773 Exec_Master_Log_Pos: 4156773

服务器C:

Master_Log_File: mysql-bin3306.000001  
Read_Master_Log_Pos: 83795320 Exec_Master_Log_Pos: 8379532

从上面可以看出服务器B的进度比服务器C更接近master

1.2

如果在传统的复制情况下,将C设置为B的从库,那将需要之前主句的log_pos和当前要设置成主库的log_pos,此时计算很容易出错,而且比较麻烦

那么在gtid的情况下,因为同一事物的GTID在所有节点上的值是一样的,所以可以直接将C的主库定位到B即可,但需要注意的是,此时千万不能执行reset master,不然C会从最先的GTID开始执行

具体顺序如下:

mysql> stop slave;   
Query OK, 0 rows affected (0.02 sec)

mysql>  change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3307,master_auto_position=1; #指定到另一个比较接近主的从上。   
Query OK, 0 rows affected, 2 warnings (0.02 sec)   
mysql> start slave; #成功的切换到新主   
Query OK, 0 rows affected (0.03 sec)

此时即完成了新主的切换

2、测试跳过复制错误

模拟出现了错误

mysql> show slave status\G;  
***************************  1. row ***************************  
Slave_IO_State: Waiting for master to send event  
Master_Host: 127.0.0.1  
Master_User: rep  
Master_Port: 3306  
Connect_Retry: 60  
Master_Log_File: mysql-bin3306.000001  
Read_Master_Log_Pos: 38260944  
Relay_Log_File: mysqld-relay-bin3307.000002  
Relay_Log_Pos: 369  
Relay_Master_Log_File: mysql-bin3306.000001  
Slave_IO_Running: Yes  
Slave_SQL_Running: No  
Replicate_Do_DB:  
Replicate_Ignore_DB:  
Replicate_Do_Table:  
Replicate_Ignore_Table:  
Replicate_Wild_Do_Table:  
Replicate_Wild_Ignore_Table:  
Last_Errno: 1008  
Last_Error: Error 'Can't drop  database  'mablevi'; database doesn't exist'  on query. Default  database: 'mablevi'. Query: 'drop database mablevi'  
Skip_Counter: 0  
Exec_Master_Log_Pos: 151  
Relay_Log_Space: 38261371  
Until_Condition:  
None Until_Log_File:  
Until_Log_Pos: 0  
Master_SSL_Allowed: No  
Master_SSL_CA_File:  
Master_SSL_CA_Path:  
Master_SSL_Cert:  
Master_SSL_Cipher:  
Master_SSL_Key:  
Seconds_Behind_Master: NULL  
Master_SSL_Verify_Server_Cert: No  
Last_IO_Errno: 0  
Last_IO_Error:  
Last_SQL_Errno: 1008  
Last_SQL_Error: Error 'Can't drop  database  'mablevi'; database doesn't exist'  on query. Default  database: 'mablevi'. Query: 'drop database mablevi'  
Replicate_Ignore_Server_Ids:  
Master_Server_Id: 1  
Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e  
Master_Info_File: mysql.slave_master_info  
SQL_Delay: 0 #通过在change的时候指定,如:change master to master_delay=600,延迟10分钟同步。  
SQL_Remaining_Delay: NULL  
Slave_SQL_Running_State:  
Master_Retry_Count: 86400  
Master_Bind:  
Last_IO_Error_Timestamp:  
Last_SQL_Error_Timestamp: 150810  23:38:39  
Master_SSL_Crl:  
Master_SSL_Crlpath:  
Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-48  
Executed_Gtid_Set:  
Auto_Position: 1

在传统的复制情况下,只需执行set global sql_slave_skip_counter=1;就好了,但在gtid的模式下不行,因为是通过gtid来复制的,需要跳过这个事物来继续复制,这个事务可以在主上的binlog里面查看:因为不知道找哪个GTID上出错,所以也不知道如何跳过哪个GTID。但在show slave status里的信息里可以找到在执行Master里的POS:454,

Relay_Log_File: localhost-relay-bin.000005
Relay_Log_Pos: 454
Exec_Master_Log_Pos: 151(这个暂时不知道作用)

的时候报错,所以通过mysqlbinlog找到了GTID:

# at 454 #150810  22:57:45 server id 1 end_log_pos 599 CRC32 0x5e14d88f GTID [commit=yes]  
SET  @@SESSION.GTID_NEXT=  '4e659069-3cd8-11e5-9a49-001c4270714e:1'/*!*/;

(需要验证)
或者在show slave status中找到Retrieved_Gtid_Set:4e659069-3cd8-11e5-9a49-001c4270714e:1

找到了这个GTID之后,就可以接着执行以下(要按顺序):

mysql> stop slave;  
Query OK, 0 rows affected (0.01 sec)  
mysql>  set  session  gtid_next='4e659069-3cd8-11e5-9a49-001c4270714e:1'; #在session里设置gtid_next,即跳过这个GTID  
Query OK, 0 rows affected (0.01 sec)  
mysql>  begin; #开启一个事务  
Query OK, 0 rows affected (0.00 sec)  
mysql>  commit;  
Query OK, 0 rows affected (0.01 sec)  
mysql>  SET SESSION GTID_NEXT = AUTOMATIC; #把gtid_next设置回来  
Query OK, 0 rows affected (0.00 sec)  
mysql> start slave; #开启复制  
Query OK, 0 rows affected (0.01 sec)

之后show slave status查看即可发现已跳过了该错误继续同步

3、跳过错误/事务例子2

mysql > stop slave;  
Query OK, 0 ROWS affected (0.05 sec)  
mysql > CHANGE master TO MASTER_DELAY=600;  
Query OK, 0 ROWS affected (0.27 sec)    
mysql > START slave;  
Query OK, 0 ROWS affected, 1 warning (0.06 sec)

master 原本是正常的, 然后意外地执行了 truncate table:

mysql > INSERT INTO t SET title='c';  
Query OK, 1 ROW affected (0.03 sec)  
mysql > INSERT INTO t SET title='d';  
Query OK, 1 ROW affected (0.05 sec)  
mysql > SHOW master STATUS \G  
*************************** 1\. ROW ***************************  
File: black-bin.000001  
POSITION: 2817  
Binlog_Do_DB:  
Binlog_Ignore_DB:  
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-10  
ROW IN SET (0.00 sec)  
mysql > TRUNCATE TABLE t;  
Query OK, 0 ROWS affected (0.15 sec)  
mysql > SHOW master STATUS \G  
*************************** 1\. ROW ***************************  
File: black-bin.000001  
POSITION: 2948  
Binlog_Do_DB:  
Binlog_Ignore_DB:  
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-11  
ROW IN SET (0.00 sec)

slave有延迟, 虽然已经获取到了gtid及对应的events, 但是并未执行:

mysql > SHOW slave STATUS \G  
*************************** 1\. ROW ***************************  
Slave_IO_State: Waiting FOR master TO send event  
.......  
.......  
SQL_Delay: 600  
SQL_Remaining_Delay: 565  
Slave_SQL_Running_State: Waiting until MASTER_DELAY seconds after master executed event  
Master_Retry_Count: 86400  
Master_Bind:  
Last_IO_Error_Timestamp:  
Last_SQL_Error_Timestamp:  
Master_SSL_Crl:  
Master_SSL_Crlpath:  
Retrieved_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:9-11  
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-8  
Auto_Position: 1  
ROW IN SET (0.00 sec)

要想办法在slave中跳过 GTID:0c005b76-d3c7-11e2-a27d-274c063b18c4:11, 也就是那条truncate table语句 。
办法就是设置GTID_NEXT,然后提交一个空的事务。

mysql > stop slave;  
Query OK, 0 ROWS affected (0.03 sec)  
mysql > SET session gtid_next='0c005b76-d3c7-11e2-a27d-274c063b18c4:11';  
Query OK, 0 ROWS affected (0.00 sec)  
mysql > BEGIN; commit;  
Query OK, 0 ROWS affected (0.00 sec)  
Query OK, 0 ROWS affected (0.01 sec)  
mysql >SET SESSION GTID_NEXT = AUTOMATIC;  
Query OK, 0 ROWS affected (0.00 sec)  
mysql > START slave;  
Query OK, 0 ROWS affected, 1 warning (0.07 sec)

查看复制状态

mysql > SHOW slave STATUS \G  
*************************** 1\. ROW ***************************  
Slave_IO_State: Waiting FOR master TO send event  
.......  
.......  
Retrieved_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:9-11  
Executed_Gtid_Set: 0c005b76-d3c7-11e2-a27d-274c063b18c4:1-11  
Auto_Position: 1  
ROW IN SET (0.00 sec)  
mysql > SELECT * FROM t;  
+----+-------+  
| id | title |  
+----+-------+  
| 1  | a     |  
| 2  | b     |  
| 3  | c     |  
| 4  | d     |  
+----+-------+  
ROWS IN SET (0.00 sec)

成功跳过 truncate table, 当然此时主从的数据已经不一致了。

注意:通过GTID的复制都是没有指定MASTER_LOG_FILE和MASTER_LOG_POS的,所以通过GTID复制都是从最先开始的事务开始,除非在自己的binlog里面有执行过之前的记录,才会继续后面的执行。

4、 要是事务日志被purge例子:

mysql> show master logs;   
+----------------------+-----------+   
| Log_name | File_size |   
+----------------------+-----------+   
| mysql-bin3306.000001  |  38260944   |   
+----------------------+-----------+   
1 row in  set (0.00 sec)  
mysql> flush logs;  
Query OK, 0 rows affected (0.03 sec)  
mysql> show tables;  
+---------------+   
| Tables_in_mmm |  
+---------------+  
| patent_family |  
| t1 |  
| t2 |  
+---------------+  
3 rows in  set (0.01 sec)  
mysql>  create  table t3(id int)engine = tokudb;  
Query OK, 0 rows affected (0.02 sec)  
mysql>  insert  into t3 values(3),(4);  
Query OK, 2 rows affected (0.05 sec) Records: 2 Duplicates: 0 Warnings: 0  
mysql> flush logs;  
Query OK, 0 rows affected (0.02 sec)  
mysql>  create  table ttt(id int)engine = tokudb;  
Query OK, 0 rows affected (0.02 sec)  
mysql>  insert  into ttt values(1),(2),(3),(4),(5);  
Query OK, 5 rows affected (0.03 sec) Records: 5 Duplicates: 0 Warnings: 0  
mysql> show master logs;  
+----------------------+-----------+  
| Log_name | File_size |  
+----------------------+-----------+  
| mysql-bin3306.000001  |  38260995  |  
| mysql-bin3306.000002  |  656  |  
| mysql-bin3306.000003  |  619  |  
+----------------------+-----------+  
3 rows in  set (0.00 sec)  
mysql> purge binary logs to  'mysql-bin3306.000003'; #日志被purge  Query OK, 0 rows affected (0.02 sec)  
mysql> show master logs; #日志被purge之后等下的binlog  
+----------------------+-----------+  
| Log_name | File_size |  
+----------------------+-----------+  
| mysql-bin3306.000003  |  619  |  
+----------------------+--------+   

3308登陆之后执行:

mysql> change master to master_host='127.0.0.1',master_user='rep',master_password='rep',master_port=3306,master_auto_position=1;   
Query OK, 0 rows affected, 2 warnings (0.04 sec)  
mysql> start slave;  
Query OK, 0 rows affected (0.02 sec)  
mysql> show slave status\G 
***************************  1. row ***************************  
Slave_IO_State:  
Master_Host: 127.0.0.1  
Master_User:  
rep Master_Port: 3306  
Connect_Retry: 60  
Master_Log_File:  
Read_Master_Log_Pos: 4  
Relay_Log_File: mysqld-relay-bin3308.000001  
Relay_Log_Pos: 4  
Relay_Master_Log_File:  
Slave_IO_Running: No  
Slave_SQL_Running: Yes  
Replicate_Do_DB:  
Replicate_Ignore_DB:  
Replicate_Do_Table:  
Replicate_Ignore_Table:  
Replicate_Wild_Do_Table:  
Replicate_Wild_Ignore_Table:  
Last_Errno: 0  
Last_Error:  
Skip_Counter: 0  
Exec_Master_Log_Pos: 0  
Relay_Log_Space: 151  
Until_Condition: None  
Until_Log_File:  
Until_Log_Pos: 0  
Master_SSL_Allowed: No  
Master_SSL_CA_File:  
Master_SSL_CA_Path:  
Master_SSL_Cert:  
Master_SSL_Cipher:  
Master_SSL_Key:  
Seconds_Behind_Master: 0  
Master_SSL_Verify_Server_Cert: No  
Last_IO_Errno: 1236  
Last_IO_Error: Got fatal error 1236  from master when reading data from  binary  log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'  
Last_SQL_Errno: 0  
Last_SQL_Error:  
Replicate_Ignore_Server_Ids:  
Master_Server_Id: 1  
Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e  Master_Info_File: /var/lib/mysql3/master.info  
SQL_Delay: 0  
SQL_Remaining_Delay: NULL  
Slave_SQL_Running_State: Slave has read  all relay log; waiting for the slave I/O thread to  update it  
Master_Retry_Count: 86400  
Master_Bind:  
Last_IO_Error_Timestamp: 150811  00:02:50  
Last_SQL_Error_Timestamp:  
Master_SSL_Crl:  
Master_SSL_Crlpath:  
Retrieved_Gtid_Set:  
Executed_Gtid_Set:  
Auto_Position: 1

报错:

Last_IO_Errno: 1236  
Last_IO_Error: Got fatal error 1236  from master when reading data from  binary  log: 'The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires.'

这里需要解决的是:Slave如何跳过purge的部分,而不是在最先开始的事务执行。

在主上执行,查看被purge的GTID:

mysql> show global variables like  'gtid_purged';  
+---------------+-------------------------------------------+  
| Variable_name | Value |  
+---------------+-------------------------------------------+  
| gtid_purged | 4e659069-3cd8-11e5-9a49-001c4270714e:1-50  |  
+---------------+-------------------------------------------+  
1 row in  set (0.00 sec) 

在从上执行,跳过这个GTID:

mysql> stop slave;  
Query OK, 0 rows affected (0.00 sec)  
mysql>  set  global  gtid_purged  =  '4e659069-3cd8-11e5-9a49-001c4270714e:1-50';  
Query OK, 0 rows affected (0.02 sec)  
mysql> reset master;  
Query OK, 0 rows affected (0.04 sec)  
mysql> start slave;  
Query OK, 0 rows affected (0.01 sec)  

要是出现:

ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set  when  @@GLOBAL.GTID_EXECUTED is empty. 

则需要执行:

mysql > reset master;

到这从的同步就正常了

5、通过另一个从库恢复从库数据

比如一台从库误操作,数据丢失了,可以通过另一个从库来进行恢复:、

slaveB(3308):

mysql>  use mmm  
Database changed  
mysql> show tables;  
+---------------+  
| Tables_in_mmm |  
+---------------+  
| patent_family |  
| t |  
| tt |  
+---------------+   
3 rows in  set (0.00 sec)  
mysql>  truncate  table tt;#误操作,把记录删除了  
Query OK, 0 rows affected (0.02 sec)  
mysql> show slave status\G  
***************************  1. row ***************************  
Slave_IO_State: Waiting for master to send event  
Master_Host: 127.0.0.1  
Master_User: rep  
Master_Port: 3306  
Connect_Retry: 60  
Master_Log_File: mysql-bin3306.000001  
Read_Master_Log_Pos: 38260553  
Relay_Log_File: mysqld-relay-bin3308.000002  
Relay_Log_Pos: 38260771  
Relay_Master_Log_File: mysql-bin3306.000001  
Slave_IO_Running: Yes  
Slave_SQL_Running: Yes  
Replicate_Do_DB:  
Replicate_Ignore_DB:  
Replicate_Do_Table:  
Replicate_Ignore_Table:  
Replicate_Wild_Do_Table:  
Replicate_Wild_Ignore_Table:  
Last_Errno: 0  
Last_Error:  
Skip_Counter: 0  
Exec_Master_Log_Pos: 38260553  
Relay_Log_Space: 38260980  
Until_Condition: None  
Until_Log_File:  
Until_Log_Pos: 0  
Master_SSL_Allowed: No  
Master_SSL_CA_File:  
Master_SSL_CA_Path:  
Master_SSL_Cert:  
Master_SSL_Cipher:  
Master_SSL_Key:  
Seconds_Behind_Master: 0  
Master_SSL_Verify_Server_Cert: No  
Last_IO_Errno: 0  
Last_IO_Error:  
Last_SQL_Errno: 0  
Last_SQL_Error:  
Replicate_Ignore_Server_Ids:  
Master_Server_Id: 1  
Master_UUID: 4e659069-3cd8-11e5-9a49-001c4270714e  
Master_Info_File: /var/lib/mysql3/master.info  
SQL_Delay: 0 #延迟同步  
SQL_Remaining_Delay: NULL  
Slave_SQL_Running_State: Slave has read  all relay log; waiting for the slave I/O thread to  update it  
Master_Retry_Count: 86400  
Master_Bind:  
Last_IO_Error_Timestamp:  
Last_SQL_Error_Timestamp:  
Master_SSL_Crl:  
Master_SSL_Crlpath:  
Retrieved_Gtid_Set: 4e659069-3cd8-11e5-9a49-001c4270714e:1-46  Executed_Gtid_Set: 081ccacf-3ce4-11e5-9a95-001c4270714e:1, #多出了一个GTID(本身实例执行的事务) 4e659069-3cd8-11e5-9a49-001c4270714e:1-46  
Auto_Position: 1  

数据被误删除之后,最好停止复制:

mysql > stop slave;   

恢复数据从slave1(3307)上备份数据,并还原到slave2(3308)中。
备份:

mysqldump -uzjy -p123456 -h127.0.0.1  -P3307 --default-character-set=utf8 --set-gtid-purged=ON -B mmm > mmm1.sql   

在还原到slaveB的时候需要在slave2上执行:reset master; 不然会报错:

ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set  when  @@GLOBAL.GTID_EXECUTED is empty. 

还原:

 mysql -uroot -p123456 -h127.0.0.1  -P3308 --default-character-set=utf8 < mmm.sql   

开启同步:

mysql> start slave;   
Query OK, 0 rows affected, 1 warning (0.03 sec)   

这时候你会发现误删除的数据已经被还原,并且复制也正常。因为根据GTID的原理,通过slave1的备份直接可以和Master进行同步。

这里备份注意的一点是:在备份开启GTID的实例里,需要指定 --set-gtid-purged参数,否则会报warning:

Warning: A partial dump from a server that has GTIDs will by default include the GTIDs of all transactions, even those that changed suppressed parts of the database. If you don't want to restore GTIDs, pass --set-gtid-purged=OFF. To make a complete dump, pass --all-databases --triggers --routines --events

备份文件里面会出现:

SET @@GLOBAL.GTID_PURGED='4e659069-3cd8-11e5-9a49-001c4270714e:1-483';

还原的时候会要求先在实例上reset master,不然会报错:

Warning: Using a password on the command line interface can be insecure. ERROR 1840 (HY000) at line 24: @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty.

指定--set-gtid-purged=ON参数,出现GTID_PURGED,直接还原的时候执行,从库不需要其他操作就可以直接change到主。

总结:

要是主从结构只有一台Master和一台Slave对于GTID来说就没有优势了,而对于2台主以上的结构优势异常明显,可以在数据不丢失的情况下切换新主。
使用GTID需要注意的是:在构建主从复制之前,在一台将成为主的实例上进行一些操作(如数据清理等),通过GTID复制,这些在主从成立之前的操作也会被复制到从服务器上,引起复制失败。即:通过GTID复制都是从最先开始的事务日志开始,即使这些操作在复制之前执行。比如在server1上执行一些drop、delete的清理操作,接着在server2上执行change的操作,会使得server2也进行server1的清理操作。

建议开启的参数:

relay_log_recovery
当slave从库宕机后,假如relay-log损坏了,导致一部分中继日志没有处理,则自动放弃所有未执行的relay-log,并且重新从master上获取日志,这样就保证了relay-log的完整性。默认情况下该功能是关闭的,将relay_log_recovery的值设置为 1时,可在slave从库上开启该功能,建议开启。

slave_parallel_workers和slave_parallel_type(提升主从复制效率)
在MySQL 5.7中,引入了基于组提交的并行复制(Enhanced Multi-threaded Slaves),设置参数slave_parallel_workers>0并且global.slave_parallel_type=‘LOGICAL_CLOCK’
变量slave-parallel-type可以有两个值:DATABASE 默认值,基于库的并行复制方式;LOGICAL_CLOCK:基于组提交的并行复制方式

参考:

http://www.cnblogs.com/zhoujinyi/p/4717951.html
https://www.cnblogs.com/andy6/p/6979590.html
https://blog.csdn.net/anzhen0429/article/details/77658663

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容