mariadb中的GTID研究

Mysql 5.6的GTID没有深入研究,初步看了下,mariadb10的GTID复制使用起来,相比5.6的要简单,传统模式复制改GTID复制,只需要CHANGE MASTER master_use_gtid=current_pos 就可以了。

本文是在mariadb 10关于GTID复制的官方文档 https://mariadb.com/kb/en/mariadb/mariadb-documentation/replication-cluster-multi-master/replication/global-transaction-id/

写的笔记和知识点,有些理解可能不完全正确,建议看官方文档。

Markdown 格式写的,新手,排版比较丑:)

From version 10.0.2, MariaDB supports global transaction IDs for replication.

Benefits
  1. Easy to change a slave server to connect to and replicate from a different master server.
  2. The state of the slave is recorded in a crash-safe way.
缺点
  1. mariadb 10的GTID实现和mysql 5.6的不一样,目前两者不兼容,也就是说mysql 5.6 master 启用GTID后,mysql 5.6的binlog event无法复制到mariadb,目前无解,官方解释如下。Mysql 5.6以后,非官方的mysql版本(percona和mariadb)和官方mysql版本差异越来越大,选择mysql版本,就要慎重了。。。
实现:
  • GTID位置信息存放在mysql.gtid_slave_pos表,在更新数据的同一事务中更新此表的最新位置信息。老版的复制,使用relay-log.info文件,和实际的数据更新是非依赖关系,crash时容易出问题。
  • 使用GTID,不需要特别的设置,只需要slave change master使用新的语法,默认是旧的复制机制。
GTID组成
0-1-10
  • The first number 0 is the domain ID, which is specific for global transaction ID (more on this below). It is a 32-bit unsigned integer.

    由于Mariadb 特有的多源复制,需要特别的加domain ID,通过domain id来区分多个源。单master的环境下, domain id可以忽略,以默认值0来表示。

  • The second number is the server ID, the same as is also used in old-style replication. It is a 32-bit unsigned integer.

  • The third number is the sequence number. This is a 64-bit unsigned integer that is monotonically increasing for each new event group logged into the binlog

使用GTID
  • From MariaDB 10.0.2, global transaction ID is enabled automatically. 默认自动启用GTID。

  • SHOW BINLOG EVENTS的结果如下:

    +------------------+------+-------------------+-----------+-------------+------------------------------------------------+

    | Log_name | Pos | Event_type | Server_id | End_log_pos | Info |

    +------------------+------+-------------------+----------->>> +-------------+------------------------------------------------+

    | mysql-bin.000041 | 4 | Format_desc | 862413307 | 248 | Server ver: 10.0.10-MariaDB-log, Binlog ver: 4 |

    | mysql-bin.000041 | 248 | Gtid_list | 862413307 | 287 | [0-862413307-5445551]

    可以看出新增加的binlog evnet "Gtid_list" = 0-862413307-5445551 ,862413307 是server id

  • 查看从库的当前GTID 值,使用命令 SELECT @@GLOBAL.gtid_slave_pos,主库上返回空值。

  • 即使使用旧的复制方式,slave上的gtid_slave_pos,也是一直记录着。但若主库是5.5,则slave上的gtid_slave_pos则是空值,因为主库的5.5.*版本还没有gtid模式。

  • 查看master的当前gtid值,使用命令 select @@global.gtid_current_pos;

    +---------------------------+

    | @@global.gtid_current_pos |

    +---------------------------+

    | 0-862413307-7175755 |

    +---------------------------+

  • 从库采用gtid的复制,语法为:CHANGE MASTER TO master_use_gtid = { slave_pos | current_pos | no }

  • 一般使用slave_pos,当A->B,A挂掉,B当master,然后A好了,想要做B的slave情况下,使用current_pos,因为B以前是主库,没有slave_pos这个值

  • GTID的限制:slave的本地写入,需要注意,因为跟master不是同一个GTID范围,写入binlog的值,复制到后续从库,容易fail,需要使用set sql_log_bin=0,来禁止binlog的写入。

    When GTID strict mode is enabled (by setting @@GLOBAL.gtid_strict_mode to 1), it is normally best to use current_pos. In strict mode, extra transactions on the master are disallowed.

    If a slave is configured with the binlog disabled, current_pos and slave_pos are equivalent.

  • 位置信息存储在 mysql.gtid_slave_pos 表

    In order to be crash-safe, this table must use a transactional storage engine such as InnoDB

    After upgrading a server to 10.0, it is necessary to run mysql_upgrade (as always) to get the table created.

  • 老版本升级到10.0系列,必须用mysql_upgrade命令来生成此表。不要直接修改此表,而应该使用命令 SET GLOBAL gtid_slave_pos = '0-1-1'

Setting up a new slave server with global transaction ID
  • Setting up from backup

    XtraBackup and mysqldump 备份得到master位置,然后BINLOG_GTID_POS函数转换为gtid位置:
    SELECT BINLOG_GTID_POS("master-bin.000001", 600);
    From version 10.0.13, mysqldump 使用--master-data时,就自动包含了gtid位置。
    得到位置后,使用如下命令,change master:

        SET GLOBAL gtid_slave_pos = "0-1-2"; -- BINLOG_GTID_POS 函数得到的位置
        CHANGE MASTER TO master_host="127.0.0.1", master_port=3310, master_user="root", master_use_gtid=slave_pos;
        START SLAVE;
    

    From version 10.0.13, mysqldump can automatically include these commands in the output if the --gtid option is used with --master-data or --dump-slave 。混合使用--master-data和--gtid ,就自动包含上述change master命令.

  • Switching an existing old-style slave to use GTID.

    很简单,只要主库是支持gtid的(10.0.2 以后 ),slave内部已经在binlog记录了gtid位置,所以切换很简单,使用如下命令:

        STOP SLAVE;
        CHANGE MASTER TO master_host="127.0.0.1", master_port=3310, master_user="root", master_use_gtid=current_pos;
        START SLAVE;
    
  • Changing a slave to replicate from a different master

    由于GTID是全局统一的,只需要指向新的IP和新的端口即可

        STOP SLAVE;
        CHANGE MASTER TO master_host='127.0.0.1', master_port=3312;
        START SLAVE;
    
gtid_strict_mode
set @@GLOBAL.gtid_strict_mode to 1 禁止slave上单独的操作。
遇到错误时,可以关闭严格模式,使用 START SLAVE UNTIL master_gtid_pos=XXX 来跳过

START SLAVE UNTIL master_gtid_pos = position>

If multiple GTIDs are specified, then they must be with distinct replication domain ID, for example:

START SLAVE UNTIL master_gtid_pos = "1-11-100,2-21-50"

MASTER_GTID_WAIT(gtid-list[, timeout)
GTID有关的三个全局变量
select @@global.gtid_slave_pos, @@global.gtid_binlog_pos,@@global.gtid_current_pos;
  • gtid_slave_pos:

This variable is the GTID of the last event group replicated on a slave server, for each replication domain.

  • gtid_binlog_pos:

This variable is the GTID of the last event group written to the binary log, for each replication domain.

  • gtid_current_pos:

This variable is the GTID of the last change to the database for each replication domain. Such changes can either be master events (ie. local changes made by user or application), or replicated events originating from another master server.




GTID主从复制

同一机器上三个实例,3307为maser,新造两个mariadb实例,端口分别为3309 和3310,开始搭建复制关系,版本为mariadb 10.0.10

3307 导出: mysqldump --master-data=2
导入:
mysql -u -p --socket=/tmp/mysql3309.sock mysql -u -p --socket=/tmp/mysql3310.sock

在做主从复制关系前,

[email protected](test_3309) : (none) 05:20:31>select @@global.gtid_current_pos;
+---------------------------+
| @@global.gtid_current_pos |
+---------------------------+
| 0-501113309-31329 |
+---------------------------+
1 row in set (0.02 sec)

[email protected](test_3309) : (none) 05:21:10>select @@global.gtid_current_pos;
+---------------------------+
| @@global.gtid_current_pos |
+---------------------------+
| 0-501113309-32311 |
+---------------------------+
1 row in set (0.00 sec)

[email protected](test_3309) : (none) 05:21:33>SELECT @@GLOBAL.gtid_slave_pos;
+-------------------------+
| @@GLOBAL.gtid_slave_pos |
+-------------------------+
| |
+-------------------------+
1 row in set (0.00 sec)

可以看出@@global.gtid_current_pos ,由于数据不断写入,值是变的,而@@GLOBAL.gtid_slave_pos 由于复制关系还没有搭建,目前是空值.

mysqldump备份文件里面的change master备注:-- CHANGE MASTER TO MASTER_LOG_FILE='mysql-bin.000052', MASTER_LOG_POS=394894368;

3309 端口采用原始的复制模式:

change master to master_host='192.168.50.111', MASTER_PORT=3307,master_user='', master_password='', master_log_file='mysql-bin.000052', master_log_pos=394894368;
start slave

[email protected](test_3309) : (none) 07:22:21>select @@global.gtid_current_pos;
+---------------------------+
| @@global.gtid_current_pos |
+---------------------------+
| 0-501113307-7227948 |
+---------------------------+
1 row in set (0.00 sec)

[email protected](test_3309) : (none) 07:22:48>SELECT @@GLOBAL.gtid_slave_pos;
+-------------------------+
| @@GLOBAL.gtid_slave_pos |
+-------------------------+
| 0-501113307-7227956 |
+-------------------------+ 可以看到 @@GLOBAL.gtid_slave_pos 已经有值了,不管是否采用传统或者gtid模式来复制.

3309 由传统模式改为 gtid模式复制:

STOP SLAVE;
CHANGE MASTER TO master_host="192.168.50.111", master_port=3307, master_user='', master_password='', master_use_gtid=current_pos;
START SLAVE;

show slave status \G 增加内容:

Master_Server_Id: 501113307
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Current_Pos
Gtid_IO_Pos: 0-501113307-7227969

3310 端口,直接采用GTID模式的复制,方法如下:

在主库上(3307)执行 : SELECT BINLOG_GTID_POS("mysql-bin.000052", 394894368);
+------------------------------------------------+
| BINLOG_GTID_POS("mysql-bin.000052", 394894368) |
+------------------------------------------------+
| 0-501113307-7227451 | -- 得到GTID位置
+------------------------------------------------+
从库上执行:
SET GLOBAL gtid_slave_pos = "0-501113307-7227451"; -- BINLOG_GTID_POS 函数得到的位置
CHANGE MASTER TO master_host="192.168.50.111", master_port=3307, master_user='', master_password='', master_use_gtid=slave_pos;
START SLAVE;

show slave status \G
Master_Server_Id: 501113307
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 0-501113307-7228013

切换master实验,把3310端口的slave的master从 3307 端口,切换到3309端口

STOP SLAVE;
CHANGE MASTER TO master_host="192.168.50.111", master_port=3309
START SLAVE;

show slave status \G
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.50.111
Master_User: rep
Master_Port: 3309
Master_Server_Id: 501113309
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 0-501113307-7280903 -- 虽然切换到3309 ,gtid的server-id,还是3307的,501113307

再切回来,把对应的master指向3307端口

STOP SLAVE;
CHANGE MASTER TO master_host="192.168.50.111", master_port=3307
START SLAVE;

[email protected](test_3310) : (none) 03:29:42>show slave status \G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.50.111
Master_User: rep
Master_Port: 3307
Connect_Retry: 60
Master_Log_File: mysql-bin.000052 --变回3307 端口的了
Read_Master_Log_Pos: 425706839
Master_Server_Id: 501113307
Master_SSL_Crl:
Master_SSL_Crlpath:
Using_Gtid: Slave_Pos
Gtid_IO_Pos: 0-501113307-7281435 GTID的前两段,不变,也就是全局唯一

三个全局变量:

select @@global.gtid_slave_pos, @@global.gtid_binlog_pos,@@global.gtid_current_pos;

  • mariadb 
  • gtid

你可能感兴趣的:(MySQL)