1. 程式人生 > >初識MariaDB之8——GTID主從復制

初識MariaDB之8——GTID主從復制

mysql mariadb gtid

一、背景介紹

在MySQL5.6之前,主從復制是通過binlog和position實現的,當A主機宕機後,B主機成為新的主節點,此時在C主機上需要使用sql語句:CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS='xxx';將自己的復制源指向B主機,難點在於,同一個事務在每臺機器上的binlog名字和位置都不一樣,怎麽找到C主機當前同步停止點在B主機上的master_log_file和master_log_pos位置就成了問題

技術分享圖片技術分享圖片

於是MySQL在5.6.2之後產生了GTID,即全局事務ID(global transaction ID),其形式為:DomainID-ServerID-TransactionID,在配置是必須確保每個MySQL服務器的server_id都不相同,同一GTID事務在每個節點上都是相同的。

二、GTID與binlog

需要註意的是Mariadb的gtid配置方式與MySQL不相同,二者之間不兼容。MaraDB在10.0.2之後的版本默認是啟用的,即使從服務器使用的是binlog和position進行主從復制,但他仍是采用GTID進行追蹤

技術分享圖片技術分享圖片

這就意味著原先的slave配置可以簡單的切換到GTID模式

STOP SLAVE;

CHANGE MASTER TO master_host='xxxx', master_port=3306, master_user='xxx',master_password='xxx',master_use_gtid=current_pos;

START SLAVE;

而從GTID模式切換回以前的binlog模式也不復雜

STOP SLAVE;

CHANGE MASTER TO MASTER_HOST='xxx', MASTER_LOG_FILE='xxx', MASTER_LOG_POS='xxx';

START SLAVE;

三、master_use_gtid介紹

master_use_gtid = { slave_pos | current_pos | no }有3種選項:

slave_pos:slave將Master最後一個GTID的position復制到本地,Slave主機可通過gtid_slave_pos變量查看最後一個GTID的position

current_pos:假設有AB兩臺主機,A是Master,當A故障後,B成為Master,A修復後以Slave的身份重新添加,A之前從沒擔任過slave角色,所以沒有之前復制的GTID號,此時gtid_slave_pos為空,為了能讓A能自動添加為Slave,此時就用到該選項。該選項是大多數情況下使用的選項,因為他簡單易用同,不必在意服務器之前是Master還是Slave角色。但要註意不要讓從服務器在binlog日誌中寫入事務。

建議在服務器上啟用gtid_strict_mode,這樣非Master產生的事物將被拒絕。如果從服務器沒有開啟binlog上面兩種方式等價。

no:關閉GTID功能

四、環境及Maradb配置介紹

本次實驗采用CentOS7.4,數據庫版本為MariaDB-10.2.14,拓撲如下圖所示:

技術分享圖片技術分享圖片

本次模擬當A主機故障後C主機將Master主機重新指向B主機,並且當A主機修復後以Slave的身份重新加入集群

三、操作步驟

1.3臺服務器安裝MariaDB-10.2.14(略)

2.A主機操作

(1)編輯配置文件

[root@host3 ~]# vim /etc/my.cnf.d/server.cnf

[mysqld]

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

skip_name_resolve=ON

relay_log=mysql-relaylog

relay_log_index=mysql-relaylog

relay_log_purge=OFF

slow_query_log=ON

server-id=10

innodb_file_per_table=ON

binlog_format=ROW

log_bin=mysql-binlog

log_slave_updates=ON

gtid_strict_mode=ON

(2)啟動並進入MySQL

[root@host3 ~]# systemctl start mariadb.service

[root@host3 ~]# mysql

(3)創建一個用於主從復制的賬號

MariaDB [(none)]> grant replication slave on *.* to 'bak'@'172.16.10.%' identified by 'bakpass';

MariaDB [(none)]> flush privileges;

(4)備份當前數據庫並發送給B主機

[root@host3 ~]# mysqldump -uroot --single-transaction --databases=hellodb --masterdata=2 --quick > /tmp/hello.sql

[root@host3 ~]# scp -r /tmp/hellodb.sql [email protected]:/tmp

(5)之後做任意DML操作,查看當前 gtid_binlog_pos

MariaDB [hellodb]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-10-40 |

| gtid_binlog_state | 0-10-40 |

| gtid_current_pos | 0-10-40 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | |

| gtid_strict_mode | ON |

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

3.B主機操作(以備份形式復制)

(1)編輯配置文件

[root@host4 ~]# vim /etc/my.cnf.d/server.cnf

[mysqld]

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

skip_name_resolve=ON

relay_log=mysql-relaylog

relay_log_index=mysql-relaylog

relay_log_purge=OFF

slow_query_log=ON

server-id=20

innodb_file_per_table=ON

binlog_format=ROW

log_bin=mysql-binlog

log_slave_updates=ON

gtid_strict_mode=ON

(2)查看備份時A主機的gtid_slave_pos位置

[root@host4 ~]# cat /tmp/hello.sql

技術分享圖片技術分享圖片

(3)登陸MySQL,創建一個用於主從復制的賬號

[root@host4 ~]# systemctl start mariadb.service

[root@host4 ~]# mysql

MariaDB [(none)]> grant replication slave on *.* to 'bak'@'172.16.10.%' identified by 'bakpass';

MariaDB [(none)]> flush privileges;

(4)以備份方式還原並同步數據庫

MariaDB [(none)]> source /tmp/hellodb.sql;

MariaDB [(none)]> SET GLOBAL gtid_slave_pos = '0-10-38';

MariaDB [(none)]> CHANGE MASTER TO master_host='172.16.10.30', master_port=3306, master_user='bak', master_password='bakpass',master_use_gtid=slave_pos;

MariaDB [(none)]> start slave;

(5)驗證效果

MariaDB [hellodb]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-10-40 |

| gtid_binlog_state | 0-20-37,0-10-40 |

| gtid_current_pos | 0-10-40 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-10-40 |

| gtid_strict_mode | ON |

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

可以看到gtid_binlog_pos已經和A主機保持一致,之前導入數據庫和創建復制賬號所以B主機上gtid_binlog_state有2個值,官方建議開啟gtid_strict_mode選項或臨時禁用sql_log_bin

4.設置C服務器(以新服務器方式同步)

(1)編輯配置文件(該服務器只作為Slave角色binlog可以不要)

[root@host5 ~]# vim /etc/my.cnf.d/server.cnf

[mysqld]

datadir=/var/lib/mysql

socket=/var/lib/mysql/mysql.sock

skip_name_resolve=ON

relay_log=mysql-relaylog

relay_log_index=mysql-relaylog

relay_log_purge=OFF

slow_query_log=ON

server-id=20

innodb_file_per_table=ON

binlog_format=ROW

log_bin=mysql-binlog

log_slave_updates=ON

gtid_strict_mode=ON

(2)啟動並進入MySQL

[root@host5 ~]# systemctl start mariadb.service

[root@host5 ~]# mysql

(3)以空服務器進行數據庫同步恢復

MariaDB [(none)]> SET GLOBAL gtid_slave_pos = "";

MariaDB [(none)]> CHANGE MASTER TO master_host='172.16.10.30', master_port=3306, master_user='bak', master_password='bakpass',master_use_gtid=current_pos;

MariaDB [(none)]> start slave;

(4)驗證效果

MariaDB [(none)]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-10-40 |

| gtid_binlog_state | 0-10-40 |

| gtid_current_pos | 0-10-40 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-10-40 |

| gtid_strict_mode | ON |

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

===================以上完成主從環境搭建=========================

5.停止A主機MySQL服務,模擬故障

[root@host3 ~]# systemctl stop mariadb.service

6.此時將B主機提升為Master主機,並進行操作

MariaDB [hellodb]> stop slave;

MariaDB [hellodb]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-10-40 |

| gtid_binlog_state | 0-20-37,0-10-40 |

| gtid_current_pos | 0-10-40 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-10-40 |

| gtid_strict_mode | ON |

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

MariaDB [hellodb]> delete from students where stuid=21;

MariaDB [hellodb]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-20-41 |

| gtid_binlog_state | 0-10-40,0-20-41 |

| gtid_current_pos | 0-20-41 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-10-40 |

| gtid_strict_mode | ON |

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

7.將C主機的Master有A指向B,並觀察變化

MariaDB [(none)]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-10-40 |

| gtid_binlog_state | 0-10-40 |

| gtid_current_pos | 0-10-40 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-10-40 |

| gtid_strict_mode | ON |

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

MariaDB [(none)]> stop slave;

MariaDB [(none)]> CHANGE MASTER TO master_host='172.16.10.40', master_port=3306, master_user='bak', master_password='bakpass',master_use_gtid=current_pos;

MariaDB [(none)]> start slave;

MariaDB [(none)]> show global variables like 'gtid%';

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

| Variable_name | Value |

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

| gtid_binlog_pos | 0-20-41 |

| gtid_binlog_state | 0-10-40,0-20-41 |

| gtid_current_pos | 0-20-41 |

| gtid_domain_id | 0 |

| gtid_ignore_duplicates | OFF |

| gtid_slave_pos | 0-20-41 |

| gtid_strict_mode | ON |

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

此時C主機的gtid_slave_pos已發生改變

MariaDB [(none)]> show variables like 'gtid_slave_pos';

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

| Variable_name | Value |

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

| gtid_slave_pos | 0-20-41 |

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

8.再將A主機以Slave的身份加入集群操作

[root@host3 tmp]# systemctl start mariadb.service

[root@host3 tmp]# mysql

MariaDB [(none)]> CHANGE MASTER TO master_host='172.16.10.40', master_port=3306, master_user='bak', master_password='bakpass',master_use_gtid=current_pos;

MariaDB [(none)]> show variables like 'gtid_slave_pos';

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

| Variable_name | Value |

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

| gtid_slave_pos | 0-20-41 |

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

至此全部操作完成

補充說明:

1.master_use_gtid = { slave_pos | current_pos }具體用哪一種仍不是很明白,文檔說current_pos適用於大部分環境,所以後期使用都是用該值。

2.Master和Candidate之間可以采用半同步方式降低數據不一致

3.雙主模式下1臺采用binlog1臺采用GTID可以正常工作


初識MariaDB之8——GTID主從復制