从mysql5.6开始引入全局事务标识符(GTID),即每个事务都有一个唯一的标识符。服务器上的每个事务都被分配一个唯一的事务标识符,这是一个64位非零的数值,根据事务提交的顺序分配。GTID的构成是由服务器的Uuid和事务的提交顺序两部分组成的。

复制事务的时候如果启用了全局事务标识符,不管事务被复制了多少次,事务的GTID保持不变。

注意的是:GTID被写入二进制日志,并且只会分配给已经写入二进制日志的事务。也就是说,如果关闭二进制日志,事务就不会分配GTID了。不管master还是slave都是这样。所以,如果想使用slave做故障转移,需要开启二进制日志,如果没有开启二进制日志,slave就不会记下事务的GTID。

首先来配置GTID复制

首先在从上清除当前的基于filename和pos的复制状态

mysql> stop slave;Query OK, 0 rows affected (0.01 sec)mysql> reset slave all;Query OK, 0 rows affected (0.02 sec)mysql> show slave status\GEmpty set (0.00 sec)

主和从均开启GTID,设置GTID复制!因为之前两台服务器时主从复制,因此状态是一致的,因此不用再拷贝数据!

同步数据,设置复制账户都需要做!因为之前已经是主从,复制账户已经存在。

binmodegtidconsistency
log-bin= #在基于filename和pos做主从时,没有开启备用服务器的二进制日志,做gtid复制时,需要开启二进制日志,原因后面会提到!
: 这个是在基于filename和pos做主从时,用于做级联复制,在MySQL5.6中左gtid好像必须要开启这个参数,MySQL5.7不再强制必须!

设置完之后重启服务器:

在从上做如下设置

mysql change master  master_host".", master_port,master_user"repl",master_password"",master_auto_position rows affected,  warnings (

# master_auto_position使slave在连接master的时候,自动与master协商应该发送什么事务。

mysql> show slave status\G                         #与之前的复制相比,多了gitd的信息
*************************** 1. row ***************************
...........
      Master_UUID: 4687e05d-f37f-11e8-8fc7-fa336351fc00               #master的UUID
           Retrieved_Gtid_Set: 4687e05d-f37f-11e8-8fc7-fa336351fc00:1-2
            Executed_Gtid_Set: 4687e05d-f37f-11e8-8fc7-fa336351fc00:1-2

Retrieved_Gtid_Set:这是从master获取而来的,存储在中继日志中的一组GTID.


Executed_Gtid_Set: 这是slave上执行,并且已经写入slave的二进制日志的一组GTID。

在从上查看二进制日志

mysql Log_name          Pos  Event_type      Server_id  End_log_pos  Info                                                               test2bin.      Format_desc                         Server ver: ., Binlog ver:                               test2bin.    Previous_gtids                                                                                         test2bin.    Gtid                                 .GTID_NEXT   test2bin.    Query                                `mytest`;   tb2(id  auto_increment  )  test2bin.    Gtid                                 .GTID_NEXT   test2bin.    Query                                                                                             test2bin.    Table_map                           table_id:  (mytest.tb2)                                         test2bin.    Write_rows                          table_id:  flags: STMT_END_F                                    test2bin.    Xid                                                                                   rows   ( sec)#在二进制日志事件中可以看到Executed_Gtid_Set的gitd集合已经在slave上执行

gitd的复制是怎么找到二进制日志的复制点的?

在我们做filename和pos的复制时,手动指定了二进制日志的文件和位置,但是gtid怎么找到二进制日志的复制点的?从上面的二进制日志看到,event有一个Previous_gtids事件,这个事件指定的是前一个二进制日志事件的最后的gtid的数值,把当前从执行到的gtid与Previous_gtids比较,确定二进制日志的文件,然后再对比gtid的大小,确定日志的位置!因为当前是一个新开始的gitd复制,因此Previous_gtids值为0,我们强制轮换主的二进制,查看数据如下!

mysql> flush logs;              #强制轮换二进制日志,会进行一次显式刷新磁盘Query OK, 0 rows affected (0.00 sec)mysql> show binlog events in "test3-bin.000006";   #因为之前的执行了两个事务,因此Previous_gtids指向为1-2.+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+| Log_name         | Pos  | Event_type     | Server_id | End_log_pos | Info                                                              |+------------------+------+----------------+-----------+-------------+-------------------------------------------------------------------+| test3-bin.000006 |    4 | Format_desc    |         5 |         123 | Server ver: 5.7.22-log, Binlog ver: 4                             || test3-bin.000006 |  123 | Previous_gtids |         5 |         194 | 4687e05d-f37f-11e8-8fc7-fa336351fc00:1-2                          || test3-bin.000006 |  194 | Gtid           |         5 |         259 | SET @@SESSION.GTID_NEXT= '4687e05d-f37f-11e8-8fc7-fa336351fc00:3' || test3-bin.000006 |  259 | Query          |         5 |         333 | BEGIN                                                             || test3-bin.000006 |  333 | Table_map      |         5 |         381 | table_id: 109 (mytest.tb1)                                        || test3-bin.000006 |  381 | Write_rows     |         5 |         421 | table_id: 109 flags: STMT_END_F                                   || test3-bin.000006 |  421 | Xid            |         5 |         452 | COMMIT /* xid=40 */                                               || test3-bin.000006 |  452 | Gtid           |         5 |         517 | SET @@SESSION.GTID_NEXT= '4687e05d-f37f-11e8-8fc7-fa336351fc00:4' |

我们知道GTID是由服务器的UUID+事务的执行顺序组成的,服务器的UUID存在于datadir指定目录下面:

mysql> show variables like "datadir";+---------------+--------------+| Variable_name | Value        |+---------------+--------------+| datadir       | /data/mysql/ |+---------------+--------------+1 row in set (0.00 sec)mysql> system cat /data/mysql/auto.cnf;           #服务器的UUID[auto]server-uuid=4687e05d-f37f-11e8-8fc7-fa336351fc00

上面我们搭建了一个简易的GITD复制,那么GTID是怎么复制的,GTID的复制原理是什么?

master更新数据时,会在事务前产生GTID,一同记录到binlog日志中。slave端的i/o线程将变更的binlog,写入到本地的relay log中。sql线程从relay log中获取GTID,然后对比slave端的binlog是否有记录。【对比本地的binlog中是否有记录,因此slave需要开通二进制日志】如果有记录,说明该GTID的事务已经执行,slave会忽略。如果没有记录,slave就会从relay log中执行该GTID的事务,并记录到binlog。

查看当前master和从的二进制日志点和gtid值!

               Position  Binlog_Do_DB  Binlog_Ignore_DB  Executed_Gtid_Set                         test3bin.                                        4687e05df37f11e88fc7fa336351fc00:  row   (               Position  Binlog_Do_DB  Binlog_Ignore_DB  Executed_Gtid_Set                         test2bin.                                         4687e05df37f11e88fc7fa336351fc00:  row   ( sec)#可以看到日志名称不一样,日志的pos不一样,但是gtid却是一样的

测试在从上插入一条数据:

mysql   tb1   row affected (  Duplicates:   Warnings:  test3bin.    Gtid                                .GTID_NEXT   test3bin.    Query                                                                                            test3bin.    Table_map                          table_id:  (mytest.tb1)                                         test3bin.    Write_rows                         table_id:  flags: STMT_END_F                                    test3bin.    Xid                                   mysql> show variables like "binlog_format";       #日志格式是row+---------------+-------+| Variable_name | Value |+---------------+-------+| binlog_format |   |+---------------+-------+1 row in set (0.00 sec)

在从上查看二进制日志

#前面执行了flush logs命令!mysql show binlog events  "test2bin. Log_name          Pos  Event_type      Server_id  End_log_pos  Info                                                               test2bin.      Format_desc                         Server ver: ., Binlog ver:                               test2bin.    Previous_gtids                      4687e05df37f11e88fc7fa336351fc00:                           test2bin.    Gtid                                 .GTID_NEXT   test2bin.    Query                                                                                             test2bin.    Table_map                           table_id:  (mytest.tb1)                                         test2bin.    Write_rows                          table_id:  flags: STMT_END_F                                    test2bin.    Xid                                                                                  rows   ( sec)

使用GTID做故障转移

#主从上都有一张这样的表,数据是一样的mysql> desc tb2;+-------+---------+------+-----+---------+----------------+| Field | Type    | Null | Key | Default | Extra          |+-------+---------+------+-----+---------+----------------+| id    | int(11) | NO   | PRI | NULL    | auto_increment |+-------+---------+------+-----+---------+----------------+1 row in set (0.00 sec)#现在在从从上插入一条数据mysql> insert into tb2 select 4;Query OK, 1 row affected (0.01 sec)Records: 1  Duplicates: 0  Warnings: 0#在主上也插入一条数据mysql> insert into tb2 select 4;Query OK, 1 row affected (0.01 sec)Records: 1  Duplicates: 0  Warnings: 0

mysql> show slave status\G*************************** 1. row ***************************               Slave_IO_State: Waiting for master to send event                  Master_Host: 10.0.102.214                  Master_User: repl                  Master_Port: 3306                Connect_Retry: 60              Master_Log_File: test3-bin.000007          Read_Master_Log_Pos: 452               Relay_Log_File: test2-relay-bin.000007                Relay_Log_Pos: 407        Relay_Master_Log_File: test3-bin.000007             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: 1062                   Last_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '4687e05d-f37f-11e8-8fc7-fa336351fc00:8' at master log test3-bin.000007, end_log_pos 421. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.                 Skip_Counter: 0          Exec_Master_Log_Pos: 194              Relay_Log_Space: 959              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: NULLMaster_SSL_Verify_Server_Cert: No                Last_IO_Errno: 0                Last_IO_Error:                Last_SQL_Errno: 1062               Last_SQL_Error: Coordinator stopped because there were error(s) in the worker(s). The most recent failure being: Worker 1 failed executing transaction '4687e05d-f37f-11e8-8fc7-fa336351fc00:8' at master log test3-bin.000007, end_log_pos 421. See error log and/or performance_schema.replication_applier_status_by_worker table for more details about this failure or others, if any.  Replicate_Ignore_Server_Ids:              Master_Server_Id: 5                  Master_UUID: 4687e05d-f37f-11e8-8fc7-fa336351fc00             Master_Info_File: /data/mysql/master.info                    SQL_Delay: 0          SQL_Remaining_Delay: NULL      Slave_SQL_Running_State:            Master_Retry_Count: 86400                  Master_Bind:       Last_IO_Error_Timestamp:      Last_SQL_Error_Timestamp: 181203 10:01:08               Master_SSL_Crl:            Master_SSL_Crlpath:            Retrieved_Gtid_Set: 4687e05d-f37f-11e8-8fc7-fa336351fc00:1-8            Executed_Gtid_Set: 4687e05d-f37f-11e8-8fc7-fa336351fc00:1-7,e2bd1bae-f5cb-11e8-9c8c-fa1dae125200:1                Auto_Position: 1         Replicate_Rewrite_DB:                  Channel_Name:            Master_TLS_Version: 1 row in set (0.00 sec)mysql>

show slave status查看复制状态

#错误说明Last_SQL_Error: Coordinator stopped because there were error(s)  the worker(s). The most recent failure being: Worker  failed executing   at master  test3bin., end_log_pos . See error   performance_schema.replication_applier_status_by_worker   more details about this failure  others,  f37f11e88fc7fa336351fc00:f37f11e88fc7fa336351fc00:f5cb11e89c8cfa1dae125200:

我们知道是重复了数值,因此忽略掉这一条gitd的执行事务即可!

mysql> select @@gtid_next;          #查看下一个要执行的事务,默认是自动选择+-------------+| @@gtid_next |+-------------+| AUTOMATIC   |+-------------+1 row in set (0.00 sec)mysql> set gtid_next="4687e05d-f37f-11e8-8fc7-fa336351fc00:8";  #我们把gtid_next设置为要忽略的哪一个事务的gtidQuery OK, 0 rows affected (0.00 sec)mysql> begin;                                                   #执行一个空的事务Query OK, 0 rows affected (0.00 sec)mysql> commit;Query OK, 0 rows affected (0.01 sec)mysql> set gtid_next="AUTOMATIC";                              #把gtid_next设置为原来的AUTOMATICQuery OK, 0 rows affected (0.00 sec)mysql> start slave sql_thread;                                 #开启sql线程Query OK, 0 rows affected (0.02 sec)mysql> show slave status\G                                      #查看复制已经恢复正常

 

©著作权归作者所有:来自51CTO博客作者Jack_jason的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. mysql的复制
  2. MySQL事务之-2
  3. MySQL事务概述-1
  4. spring项目中引入AspectJ相关的Maven依赖【复制即可】
  5. MySQL探秘(八):InnoDB的事务
  6. MySQL死锁系列-线上死锁问题排查思路
  7. 高可用数据库主从复制延时的解决
  8. 探索 Linux 上的 /run
  9. mySql 在Linux上安装

随机推荐

  1. Android指定调用系统自带浏览器打开链接
  2. Android帧布局-实现渐变效果
  3. 搭建Android开发环境01——Java
  4. Android自定义ProgressBar
  5. 查看android路由表
  6. Android修改PackageInstaller自动安装指
  7. Android SDK更新失败对策
  8. 一张图片覆盖在另一个图片上
  9. android:broadcast_01
  10. android检查sd卡是否可写