細細探究MySQL Group Replicaiton — 配置維護故障處理全集


 
 
     本文主要描述 MySQL Group Replication的簡易原理、搭建過程以及故障維護管理內容。由於是新技術,未在生產環境使用過,本文均是虛擬機測試,可能存在考慮不周跟思路有誤情況,歡迎交流指正。
 
如果轉載,請注明博文來源:  www.cnblogs.com/xinysu/   ,版權歸 博客園 蘇家小蘿卜 所有。望各位支持! 

1 What's Group Replication 

    主從復制,一主多從,主庫提供讀寫功能,從庫提供寫功能。當一個事務在master 提交成功時,會把binlog文件同步到從庫服務器上落地為relay log給slave端執行,這個過程主庫是不考慮從庫是否有接收到binlog文件,有可能出現這種情況,當主庫commit一個事務后,數據庫發生宕機,剛好它的binlog還沒來得及傳送到slave端,這個時候選任何一個slave端都會丟失這個事務,造成數據不一致情況。原理圖如下:
 
 
     為了避免出現主從數據不一致的情況,MySQL引入了半同步復制,添加多了一個從庫反饋機制,這個有兩種方式設置:
  • 主庫執行完事務后,同步binlog給從庫,從庫ack反饋接收到binlog,主庫提交commit,反饋給客戶端,釋放會話;
  • 主庫執行完事務后,主庫提交commit ,同步binlog給從庫,從庫ack反饋接收到binlog,反饋給客戶端,釋放會話;

 

    但是,但是,但是,問題來了,雖然滿足了一主多從,讀寫分析,數據一致,但是,依舊有兩個弊端
  • 寫操作集中在MASTER服務器上;
  • MASTER宕機后,需要人為選擇新主並重新給其他的slave端執行change master(可自行寫第三方工具實現,但是mysql的復制就是沒提供,所以也算是弊端)
    於是乎,官方感應到民間怨氣以及業界壓力,於2016年12月12日正式發布了MySQL Group Replication,此處應有掌聲 
    那么,MySQL Group Replication可以提供哪些功能呢?
  • 多主,在同一個group里邊的所有實例,每一個實例可以執行寫操作,也就是每個實例都執行Read-Write
    • 注意一點,多主情況下,當執行一個事務時,需要確保同個組內的每個實例都認可這個事務無沖突異常,才可以commit,如果設置的是單主,其他實例ReadOnly,則不需要進行上面的判斷
    • 多主情況下,事務並發沖突問題就凸顯出來了,如何避免呢?數據庫內部有一個認證程序,當不同實例並發對同一行發起修改,在同個組內廣播認可時,會出現並發沖突,那么會按照先執行的提交,后執行的回滾
  • 彈性,同個Group Replication中,節點的加入或者移除都是自動調整;如果新加入一個節點,該節點會自動從Group的其他節點同步數據,直到與其他節點一致;如果移除一個節點,那么剩下的實例會自動更新,不再向這個節點廣播事務操作,當然,這里要注意,假設一個Group的節點有n個(max(n)=9,同個Group最多節點數為9),移除或者宕機的節點數應該小於等於 floor((n-1)/2) ,注意是向下取整;如果是單主模式,宕機的是單主,則人為選擇新主后,其他節點也會自動從新主同步數據。
  • 更高性能的同步機制
 

 

涉及知識點
故障探測( Failure Detection):
Group Replication中有一個故障檢測機制,會提供某些節點可能死掉的信息,然后廣播給同一個Group的各個節點,如果確定宕機,那么組內的節點就會與它隔離開來,該節點即無法同步其他節點的傳送過來的binlog events,也無法執行任何本地事務。
這里有個問題,故障探測中,假設N個節點,一個節點故障,是采用多數投票機制還是全部一致投票機制?
 

2 配置要求與限制

2.1 數據庫要求

2.1.1 innodb引擎

    為什么需要使用innodb引擎呢?在MySQL Group Replication中,事務以樂觀形式執行,但是在提交時檢查沖突,如果存在沖突,則會在某些實例上回滾事務,保持各個實例的數據一致性,那么,這就需要使用到 事務存儲引擎,同事Innodb提供一些額外的功能,可以更好的管理和處理沖突,所以建議 業務使用表格使用inndb存儲引擎,類似於系統表格mysql.user使用MyISAM引擎的表格,因為極少修改及添加,極少出現沖突情況。

2.1.2 主鍵

    每個需要復制的表格都必須定義一個顯式主鍵,注意跟隱式主鍵區分(使用Innodb引擎的表格,如果沒有指定主鍵,默認選擇第一個非空的唯一索引作為主鍵,如果沒有,則自動創建一個6個字節的rowid隱式主鍵)。這個主鍵能在沖突發生時啟動極其重要的作用,同時,能夠有效提高relay log的執行效率。

2.1.3 隔離級別

    官網建議使用READ COMMITTED級別,除非應用程序依賴於REPLEATABLE READ,RC模式下沒有GAP LOCK,比較好支持Innodb本身的沖突檢測機制何組復制的內部分布式檢測機制一起協同工作。不支持SERIALIZABLE隔離級別。

2.1.4 外鍵

    不建議使用級聯外鍵,如果舊庫本身有外鍵,業務上無法去除並且使用的是多主模式,那么,請配置 group_replication_enforce_update_everywhere_check ,強制檢查每個組成員的級聯檢查,避免多主模式下執行級聯操作造成的檢測不到的沖突。

2.1.5 IPv4網絡,網絡性能穩定延遲小帶寬充足

2.1.6 自增跟步長

    這里需要注意到,搭建group的時候,每個實例中的auto_increment_increment跟auto_increment_offset的配置情況。

  • auto_increment_increment,在GROUP中范圍在1-9(因為一個GROUP最多只能有9個組成員),GROUP中安裝的時候,默認為7;
  • auto_increment_offset,增長步長,GROUP安裝過程,是等於@@server_id的,但是注意有個規則是,當 auto_increment_offset > auto_increment_increment的時候,則是忽略 auto_increment_offset的設置,第一個insert的從1開始,組內其他成員的初始值按照插入順序 1+n*組員個數,若GROUP有3個成員,A,B,C,serverid分別為2243310,2243320,3423340,A先insert,C再insert,B最后insert,則初始值 A是1,B是9,C是6 (測試結論,未找到實際說明文檔)
1 mysql> show global variables like 'auto_inc%';
2 +--------------------------+---------+
3 | Variable_name            | Value   |
4 +--------------------------+---------+
5 | auto_increment_increment | 7       |
6 | auto_increment_offset    | 2143340 |
7 +--------------------------+---------+
8 2 rows in set (0.00 sec)

 

2.2 安裝mysql_replication引擎前提

  • master info and relay log info repositories
    • master_info_repository
      • set global master_info_repository ='table';
    • relay_log_info_repository
      • set global relay_log_info_repository=‘table';
    • 如果不設置會報錯,報錯信息如下
      • [ERROR] For the creation of replication channels the master info and relay log info repositories must be set to TABLE
  • binlog_checksum
    • binlog的校驗方式應該設置為none
    • 如果不設置,報錯性能如下
    • [ERROR] Plugin group_replication reported: 'binlog_checksum should be NONE for Group Replication'

2.3 其他參數要求

  • binary log設置
    • 需要啟動記錄binary log,任何復制都需要使用到二進制內容
    • 在配置文件中添加 log-bin = [binlog存儲路徑及命名方式]
    • 例子: log-bin = /data/mysql/mysql3310/logs/bin_log
  • log-slave-updates設置
    • 默認情況下,主庫同步到從庫執行的內容,是不產生binlog日志的,一般開啟該參數是為了滿足 多級復制,比如 A->B->C(A是B的主庫,B是C的主庫),那么這個時候B就需要開啟這個參數記錄從A同步到B上面的所有操作到binary log中,這樣才能完整的同步到C上。
    • 而在MGR中,組中的server需要記錄從組接收和應用的所有事務,因為恢復的時候,是依賴域各個組的二進制日志內容的。
    • 那么這個時候,可能就有個疑問,在多主模式下,假設實例A ,B , C三台中,每個實例修改的內容都記錄到binary log中,再同步給其他組成員,那在B上執行事務 tranb : update了一行數據,tranb提交后同步到 A跟C,各自執行后,由於啟動了log-slave-updates設置,A跟C也生成了binary log,那么這些日志如果再同步回B,再執行一遍,不就可能出現問題了嗎?實際上這個擔憂是多余的,在MGR中,啟動了GTID模式,會檢查GTID EXCUTED集合,如果是已經執行的,則不會再次執行。
  • binary log格式
    • MGR依賴以及與行復制格式
    • binlog_format=row
  • GTID模式啟動
    • 組復制使用全局事務標識符來記錄哪些事務已在所有server實例上提交,從而判斷哪些是已提交事務哪些是沖突事務,避免重復執行及數據不一致
    • gtid_mode=ON
  • transaction_write_set_extraction
    • 這個神奇的參數5.7.6版本引入,用於定義一個記錄事務的算法,這個算法使用hash標識來記錄事務。如果使用MGR,那么這個hash值需要用於分布式沖突檢測何處理,在64位的系統,官網建議設置該參數使用 XXHASH64 算法。
    • transaction_write_set_extraction ='XXHASH64'
    • 官網解釋:Defines the algorithm used to generate a hash identifying the writes associated with a transaction. If you are using Group Replication, the hash value is used for distributed conflict detection and handling. On 64-bit systems running Group Replication, we recommend setting this to XXHASH64 in order to avoid unnecessary hash collisions which result in certification failures and the roll back of user transactions

3 搭建Mysql Group Replication

本次搭建采用3個實例,兩個服務器,同一個網段,MGR的參數配置在配置文件中添加。
  • 注意通訊端口號的配置,它用於組成員之間的通訊使用
  • 請確定當前MySQL版本為5.7.17或者之后版本
  • 每個實例的serverid必須是唯一標識,建議使用ip末端+端口描述
基礎信息如下:
 
實例名
A
B
C
IP
192.168.9.242
192.168.9.242
192.168.9.244
實例端口號
3310
3320
3340
Server-ID
2423310
2423320
2443340
通訊端口號
24201
24202
24404
MySQL Versoin
5.7.17
5.7.17
5.7.17
MGR參數配置方式
修改配置文件
修改配置文件
修改配置文件
 

3.1 單主模式(group_replication_single_primary_mode =ON

3.1.1 主機名修改

    為了方便后續管理維護以及一些不必要的錯誤,強烈建議修改主機名,尤其是當同個GROUP里邊的SERVER主機名都是一樣的情況下,由於本人在虛擬機中測試,虛擬機的主機名都是一樣的,導致后續出現了部分問題,建議修改。
注意在兩台SERVER上都修改哈!
 1 #查看當前主機名
 2 hostname
 3 
 4 #修改主機名
 5 hostname sutest242
 6 
 7 #進入vim /etc/hosts 
 8 #添加記錄,不要修改默認的 127.0.0.1跟::1的記錄,其他的系統服務會使用到的
 9 127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
10 ::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
11 192.168.9.242 sutest242
12 192.168.9.244 sutest244
配置后檢查如下:
 

3.1.2 設置環境變量

關於GTID及日志信息記錄相關參數(這部分的參數設置含義可以查看 第二部分:配置要求與限制
gtid_mode=on
enforce-gtid-consistency=on
binlog_gtid_simple_recovery=1
log-slave-updates=1
binlog_checksum=NONE
master_info_repository=TABLE
relay_log_info_repository=TABLE
 
關於MGR相關參數說明
transaction_write_set_extraction #記錄事務的算法
group_replication_start_on_boot #是否隨服務器啟動而自動啟動組復制
group_replication_bootstrap_group #引導組成員的組,這個用於第一次搭建MGR跟重新搭建MGR的時候使用
group_replication_group_name  #此GROUP的名字,必須是一個有效的UUID,以此來區分整個內網里邊的各個不的GROUP
group_replication_local_address #本地的IP地址字符串,host:port
group_replication_group_seeds  #需要接受本實例的信息服務器IP地址字符串
group_replication_single_primary_mode #是否啟動單主模式,如果啟動,則本實例是主庫,提供讀寫,其他實例僅提供讀
group_replication_enforce_update_everywhere_checks #多主模式下,強制檢查每一個實例是否允許該操作
 
關於MGR相關參數配置
 1 #動態配置:
 2 set global transaction_write_set_extraction='XXHASH64';
 3 set global group_replication_start_on_boot=OFF;
 4 set global group_replication_bootstrap_group = OFF ;
 5 set global group_replication_group_name= '9ac06b4e-13aa-11e7-a62e-5254004347f9'; #某個UUID
 6 set global group_replication_local_address='192.168.9.242:24201';
 7 set global group_replication_group_seeds ='192.168.9.242:24201,192.168.9.242:24202,192.168.9.242:24401';
 8 set global group_replication_ip_whitelist = '127.0.0.1/8,192.168.9.0/24';
 9 set global group_replication_single_primary_mode=True;
10 set global group_replication_enforce_update_everywhere_checks=False;
11  
12 #cnf文件配置:
13 server-id=12001
14 transaction_write_set_extraction = XXHASH64
15 loose-group_replication_group_name = '9ac06b4e-13aa-11e7-a62e-5254004347f9'
16 loose-group_replication_ip_whitelist = '127.0.0.1/8,192.168.9.0/24'
17 loose-group_replication_start_on_boot = OFF
18 loose-group_replication_local_address = '192.168.9.242:24201'
19 loose-group_replication_group_seeds = '192.168.9.242:24201,192.168.9.242:24202,192.168.9.242:24401'
20 loose-group_replication_bootstrap_group = OFF
21 loose-group_replication_single_primary_mode = true
22 loose-group_replication_enforce_update_everywhere_checks = false
 
    這一步這里采用配置文件添加的方式, 添加成功后重啟數據庫服務
 

3.1.3 建立復制賬號

GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.%' IDENTIFIED BY 'replforslave';

3.1.4 安裝引擎

INSTALL PLUGIN group_replication SONAME 'group_replication.so';
 
如果出現1123錯誤,請查看當前的數據庫版本是否是5.7.17及之后的版本,只有這些版本才有grou_replication插件
ERROR 1123 (HY000): Can't initialize function 'group_replication'; Plugin initialization function failed.
 
安裝后,引擎默認會創建一個用戶 _gr_user,提供group_replication引擎內部使用,其權限如下:
 
檢查是否安裝成功,show plugins;
 
來到了這一步,離成功已經很近了,注意檢查 步驟1-4,必須在每個實例或者server上都配置一遍。
 

3.1.5  配置Group

按照先把實例A加入Group中,由於是第一個加入Group中,需要啟動group_replication_bootstrap_group,引導組,實例A加入成功后,陸續加入實例B及實例C。
 
首先,對實例A進行操作:
 1 #實例A
 2 #1 查看當前的group replication相關參數是否配置有誤
 3 show global variables like 'group%';
 4  
 5 #2 啟動 group_replication_bootstrap_group
 6 SET GLOBAL group_replication_bootstrap_group=ON;
 7  
 8 #3 配置MGR
 9 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
10  
11 #4 啟動MGR
12 start group_replication;
13  
14 #5 查看Error log,截圖如下
15 #error log如果有問題,拉到本文末端,對應找錯誤,如果沒有解決,請google或者留言
16  
17 #6 關閉 group_replication_bootstrap_group
18 SET GLOBAL group_replication_bootstrap_group=OFF;
   
進入到數據目錄,發現新建了幾個文件:
   
*_apaplier.*  系列文件 提供 SQL_Thread 使用,存儲同個組內其他SERVER的binnary log,這個文件在第一個組成員加入組的時候,可以在Error Log看到其安裝信息。
*_recovery.* 系列文件 是做什么使用的呢,在第一個成員啟動MGR的時候,並沒有看到其相關信息,稍后解疑!
先在實例A上開始造數據,建立數據庫mgr,建立表格tb1,INSERT部分數據,操作如下:
#實例A
mysql> create database mgr;
Query OK, 1 row affected (0.01 sec)

mysql> use mgr
Database changed
mysql> create table tb1(id int primary key auto_increment not null,name varchar(100));
Query OK, 0 rows affected (0.10 sec)

mysql> insert into tb1(name) select @@server_id;
Query OK, 1 row affected (0.09 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into tb1(name) select @@server_id;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into tb1(name) select @@server_id;
Query OK, 1 row affected (0.01 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> insert into tb1(name) select @@server_id;
Query OK, 1 row affected (0.00 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> select * from tb1;
+----+---------+
| id | name    |
+----+---------+
|  6 | 2423310 |
| 13 | 2423310 |
| 20 | 2423310 |
| 27 | 2423310 |
+----+---------+
4 rows in set (0.00 sec)

mysql> show master status;
+----------------+----------+--------------+------------------+------------------------------------------+
| File           | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                        |
+----------------+----------+--------------+------------------+------------------------------------------+
| bin_log.000002 |     1795 |              |                  | 9ac06b4e-13aa-11e7-a62e-5254004347f9:1-7 |
+----------------+----------+--------------+------------------+------------------------------------------+
1 row in set (0.00 sec)
模擬數據操作
 
接着,對實例B 進行操作:
 1 #實例B
 2 #1 查看當前的group replication相關參數是否配置有誤
 3 show global variables like 'group%';
 4  
 5 #2 配置MGR
 6 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
 7  
 8 #3 啟動MGR
 9 start group_replication;
10  
11 #4 查看Error log,截圖如下
12 #error log如果有問題,拉到本文末端,對應找錯誤,如果沒有解決,請google或者留言

 

    通過errrlog,可以詳細看到啟動過程的所有步驟信息,由於新增數據,導致實例B需要使用到 group_replication_recovery 通道來恢復數據。但是是怎么一個恢復過程呢?查看 *_recovery.* 系列文件 都是只有文件頭沒有binlog內容的文件。
在加入實例C之前,再次在實例A上造數據,這次造多多數據。新建表格tb2,設置2個大字段,然后insert 2w+的數據量。
 1 #實例A
 2 mysql> use mgr
 3 Database changed
 4 mysql> create table tb2(id int auto_increment primary key not null,namea varchar(8000),nameb varchar(8000));
 5 Query OK, 0 rows affected (0.03 sec)
 6 
 7 mysql> insert into tb2(namea,nameb) select repeat('a',8000),repeat('b',8000);
 8 Query OK, 1 row affected (0.02 sec)
 9 Records: 1  Duplicates: 0  Warnings: 0
10 
11 #insert 自行操作,看試驗需要,本次需要大量數據來recovery,所以后面采用 insert into tb2 .. select .. from tb2 方式造數據 2w+
 
最后,對實例C 進行操作:
 1 #實例C
 2 #1 查看當前的group replication相關參數是否配置有誤
 3 show global variables like 'group%';
 4  
 5 #2 配置MGR
 6 CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
 7  
 8 #3 啟動MGR
 9 start group_replication;
10  
11 #4 查看Error log,截圖如下
12 #error log如果有問題,拉到本文末端,對應找錯誤,如果沒有解決,請google或者留言
通過errrlog,可以詳細看到啟動過程的所有步驟信息,由於新增數據,導致實例C需要使用到 group_replication_recovery 通道來恢復數據,這跟實例B是一模一樣的過程,但是,由於前期實例A造了大量的數據,所以在整個recovery的過程中,可以查看到  *_recovery.* 系列文件 的變化情況。
    通過error log大小的變化,是通過group_replication_recovery 通道來恢復數據,需要恢復的binary log是存放在  *_recovery.* 系列文件 ,通過本次recovery 文件查看,發現,在recovery過程中,通道內的IO_THREAD拉去日志存儲在 *_recovery.* 系列文件 中,當通道內的 SQL_Thread 完成日志應用后,則會刪除掉 *_recovery.* 系列文件 文件,新建空文件,代表已經沒有數據需要恢復。
    至此,單主模式已搭建結束,實例A可提供讀寫,但是實例B跟實例C僅提供讀服務。
   

    在搭建的過程中,也理清了兩個重要通道的使用情況:

  • group_replication_applier 通道 提供組內成員向 MASTER 實時同步binlog日志使用,這個通道內IO_thread拉取到的日志存放在 *_apaplier.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上。
  • group_replication_recovery 通道 提供 首次加入GROUP或者重新加入GROUP時恢復數據使用,這個通道內 IO_thread拉取到的日志存放在 *_recovery.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上,應用結束后,刪除所有  *_recovery.* 系列文件 ,重新建立新的 *_recovery.* 系列文件。
可以通過P_S庫中的表格查詢使用情況:SELECT * FROM mysql.slave_relay_log_info
 

3.2 多主模式group_replication_single_primary_mode =OFF

    多主模式如何配置呢,其實跟 單主模式的流程一模一樣,只需要修改 3.1 單主模式 中第二部 配置環境變量中,把 group_replication_single_primary_mode 參數設置成關閉狀態即可,然后按照 單足模式的一直執行就可以了。
# 動態修復方式
set global group_replication_single_primary_mode=OFF;
 
# 配置文件修改方式
loose-group_replication_single_primary_mode = OFF
 
    但是,既然說到配置多主模式,除了從頭就直接配置多主外,還有一種情況是,本來是單主模式,現在修改為多主模式,這個轉換過程,則是這部分要來描述的。
    首先,考慮到的是,能否直接在多主模式運行的情況下,就直接動態修改這個參數呢?因為這個參數是可以動態調整,BUT,在 GROUP_REPLICATION 運行的過程中,是不能修改這個參數的,會友好的提示您:
 
 
    所以,需要新停掉GROUP_REPLICATION。
 
    操作流程:業務端連接IP處理 -> GROUP內成員逐個依次主動退出GROUP -> 關閉 group_replication_single_primary_mode參數-> 逐個啟動GROUP內的SERVER

3.2.1 業務端連接IP處理  

    對程序端端影響:如果是程序直連主庫,則不需要操心這個過程,但是如果是通過第三方工具檢查GROUP中的主庫是哪個的話,需要先修改第三方工具直連原主庫,因為所有Group內的成員都要停止服務,如果都是自動判斷的話,最后會找不到GROUP中的成員的,所以,在開始切換的時候,就需要業務方固定讀寫在實例A上。

3.2.2 GROUP內成員逐個依次主動退出GROUP

連接實例A:
1 #實例A
2 stop group_replication;
3  
4 #檢查實例B,C的error log,發現實例A主動退出,group成員刪除實例A
Error Log內容如下:
 
    這個時候,A可讀寫,但是不在group中,其binlog內容不會在組內同步;C升級自動升級為主庫,可讀寫,binlog會同步到B上。 這里的主庫升級,是看MEMBER_ID的升序排序情況,最小的升級為主庫
在B上通過表格 replication_group_members跟global_status,可以查看現在的組成員以及主庫是哪個。查看截圖如下: 
 
連接實例B:
1 #實例B 2 stop group_replication; 3 4 #檢查實例B,C的error log,發現實例A主動退出,group成員刪除實例A
 
    這個時候,A,B均可以讀寫,但是不在GROUP中,業務目前在A上運行,C也可以讀寫,目前是主庫。
 
連接實例C:
#實例c
stop group_replication;
   
    這個時候,整個GROUP內的所有成員都依次自動退出了GROUP。

3.2.3 關閉 group_replication_single_primary_mode參數

    需要修改2個地方,第一個是動態修改參數,第二個是到配置文件中修改參數(防止DB服務重啟,參數失效)!
#動態修改
#實例A
set global group_replication_single_primary_mode =OFF
 
#實例B
set global group_replication_single_primary_mode =OFF
 
#實例C
set global group_replication_single_primary_mode =OFF
 
 
#配置文件添加
#實例A的cnf文件中修改
loose-group_replication_single_primary_mode = OFF
 
#實例B的cnf文件中修改
loose-group_replication_single_primary_mode = OFF
 
#實例C的cnf文件中修改
loose-group_replication_single_primary_mode = OFF
 
為了模擬有業務在實例A上操作,在實例A上創建表格 tb4,並導入tb2的所有數據
 
#實例A
mysql> create table tb4 like tb2;
Query OK, 0 rows affected (0.18 sec)
 
mysql> insert into tb4 select * from tb2;
Query OK, 20480 rows affected (33.13 sec)
Records: 20480  Duplicates: 0  Warnings: 0

3.2.4 逐個啟動GROUP內的SERVER

    首先針對實例A啟動,然后啟動實例B,緊接着啟動實例C。這個過程中,每加入一個組成員,記得去看error log是否有報錯。
當A啟動的時候,可以看到成了一個新的GROUP,B加入到時候,需要通過 group_replication_recovery 通道恢復數據,C加入到時候,也需要通過 group_replication_recovery 通道恢復數據,這部分的內容跟 3.1. 5 配置Group 中的errorlog內容差不多,這里就不做截圖分析。
 
#實例A
#需要啟動 group_replication_bootstrap_group 引導組,啟動后需要關閉,防止腦裂
mysql> set global group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)
 
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)
 
mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (1.16 sec)
 
mysql> set global group_replication_bootstrap_group=Off;
Query OK, 0 rows affected (0.00 sec)
 
#實例B
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.04 sec)
 
mysql> start group_replication;
Query OK, 0 rows affected (4.31 sec)
 
#實例C
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.07 sec)
 
mysql> start group_replication;
Query OK, 0 rows affected (3.83 sec)

3.2.5 檢查現在GROUP情況

目前GROUP中的各個成員都關閉了super_read_only選項,提供了讀寫服務,由於三個都為主庫,屬於多主情況,所以 global_status中無法查看到主庫是哪個,因為這個GROUP中,每個SERVER都是MASTER。
 
mysql> select * from performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 2ec0fecd-16a2-11e7-97e1-52540005b8e1 | sutest244   |        3340 | ONLINE       |
| group_replication_applier | 94e39808-15ed-11e7-a7cf-52540005b8e2 | sutest242   |        3310 | ONLINE       |
| group_replication_applier | 9b78d231-15ed-11e7-a82a-52540005b8e2 | sutest242   |        3320 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.21 sec)
 
mysql> select * from performance_schema.global_status where variable_name like '%group%';
+----------------------------------+----------------+
| VARIABLE_NAME                    | VARIABLE_VALUE |
+----------------------------------+----------------+
| group_replication_primary_member |                |
+----------------------------------+----------------+
1 row in set (0.35 sec)
 
mysql> show global variables like 'group_replication_single_primary_mode';
+---------------------------------------+-------+
| Variable_name                         | Value |
+---------------------------------------+-------+
| group_replication_single_primary_mode | OFF   |
+---------------------------------------+-------+
1 row in set (0.33 sec)
 
mysql> show global variables like 'super%';
+-----------------+-------+
| Variable_name   | Value |
+-----------------+-------+
| super_read_only | OFF   |
+-----------------+-------+
1 row in set (1.20 sec)
至此,多主模式已搭建結束,實例A、B、C均可提供讀寫。PS: 這里需要注意沖突處理機制,可以查看第五部分的故障模擬。
 

4 管理維護

這部分內容主要涉及到幾個系統表格,有點類似於 SQL SERVER中的DMV視圖,詳見下表。
id table_schema table_name type description
1 performance_schema replication_group_members 重要,常用 查看GROUP成員。
2 performance_schema replication_group_member_stats 重要,常用 當前SERVER在GROUP中的同步情況,查看applier通道的同步情況。
3 performance_schema replication_connection_stats 重要,常用 當前server中各個通道的使用情況,applier通道是一定有顯示,recovery通道看是否使用過,如果有則顯示,沒有則不顯示。
4 performance_schema replication_applier_stats 重要,常用 當前server中各個通道是否啟用。
5 performance_schema global_status 重要,常用 單主模式下,可以查看當前主庫是哪個。
6 performance_schema replication_applier_configuration 不常用,了解即可  
7 performance_schema replication_applier_status_by_coordinator 不常用,了解即可  
8 performance_schema replication_applier_status_by_worker 不常用,了解即可  
9 performance_schema replication_connection_configuration 不常用,了解即可  
10 mysql slave_master_info 重要,不常用 設置了master_info_repository=TABLE,所以master的相關信息會存儲在這個表格。
如果使用GROUP中的SERVER備份數據庫,恢復到時候,注意要清理這個表格。
11 mysql slave_relay_log_info 重要,不常用 設置了relay_log_info_repository=TABLE,所以master的相關信息會存儲在這個表格。
如果使用GROUP中的SERVER備份數據庫,恢復到時候,注意要清理這個表格。
 

4.1 查看GROUP中的成員有哪些

SELECT * FROM performance_schema.replication_group_members

4.2 單主模式下主庫是哪個

SELECT * FROM performance_schema.replication_group_members;
SELECT * FROM performance_schema. global_status;
兩個查詢出來的UUID一致的為 主庫。

4.3 檢查數據庫是否正常提供讀寫服務 

show global variables like 'super%';
SELECT * FROM performance_schema.replication_group_members;
 
如果super_read_only是啟動的,那么該成員僅提供讀服務;
如果super_read_only是關閉的,並且 replication_group_members 中正常的成員n 滿足 2n+1 > 整個GROUP成員個數,並且該成員的 member state是online,則該成員可提供讀寫服務。
 

4.4 檢查數據庫是否復制出現問題

可以通過表格replication_group_members ,replication_group_member_stats ,replication_connection_stats ,replication_applier_stats 查看
重點注意各個 組成員的 ERROR LOG詳細信息,因為報錯描述最清楚都在這里了。

5 故障模擬及處理

節選測試過程的圖,跟之前配置的GROUP有些不一致,理解注重思路即可,部分測試細節沒有再次描述。

5.1 單主模式

5.1.1 主庫宕機,如何自動選擇新主庫?各個實例之間的super_read_only模式如何切換?

select * from performance_schema.replication_group_members;
select * from performance_schema.global_status where VARIABLE_NAME='group_replication_primary_member';
show global variables like 'server_uuid';
show global variables like 'super%';
 
select * from performance_schema.replication_connection_status;
select * from performance_schema.replication_applier_status;

 

 

     模擬group中,有三個實例,端口分別為 3320,3330,3340,用簡稱來 m3320、m3330、m3340來分別描述。

    m3330在屬於主庫,模擬其主庫宕機,使用 kill 進程方式,當m3330宕機后,m3320及m3340檢查到 timeout reading,則會從group_member中剔除該實例,同時檢測宕機實例是否小於 floor((n-1)/2) (n為group中所有實例個數),如果滿足,則啟動新的GROUP,按照GROUP中各個實例的UUID進行 升序排序,選擇第一個作為新的主庫,由於新主庫之前是super_read_only狀態,僅支持只讀,升級為新主庫后,會執行 ,不設置 super_read_only,關閉此參數,那么新主庫則是可提供讀寫服務,原先的從庫現在依舊為從庫,super_read_only依舊為啟動狀態,僅提供讀服務。

5.1.2 主庫宕機后,恢復,重新加入group

    舊主庫恢復后,檢查GROUP_REPLICATION相關參數,是否設置有誤,它需要以一個從庫的方式加入,詳見 GROUP配置的參數說明。
如果參數無誤,執行change master,然后start 即可。
 
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;
    其他兩個節點檢查連接情況,連接無誤后,加入group中,更新 GROUP Member,同時開始同步差異binlog日志內容。

5.1.3 從庫宕機1台,影響情況

    kill 3330進程,模擬從庫宕機,發現剩下實例檢測到 m3330異常,從 group中刪除,主庫m3320照常提供讀寫服務,從庫m3340照常提供讀服務。

5.1.4 從庫宕機2台,影響情況

    基於3的基礎上,再次kill 3340進程,模擬從庫宕機,主庫3320檢查到 m3340異常,但是沒有刪除該 成員,而是便是為 unreachable,表明該成員可能由於崩潰或者意外被斷開而導致的不可訪問。
    或者(兩個從庫宕機的時刻非常接近,則來不及判斷剔除出group)
 
    對僅存活動 m3320 執行查詢操作,是正常情況。但是DDL及DML 操作,均處於等待狀態,並且,error log也無報錯情況。
 

    這個時候,如果想要恢復主庫讀寫服務,需停止group(這里有個疑問,查看replication_applier_status,主庫狀態正常;但是不提供讀寫應該從哪個地方判斷呢,難道是group_member的正常個數不滿足group的正常個數要求,則不提供服務?除了stop group_relication和新加入節點外,還有其他方式處理嗎?
 

5.1.5 新增從庫:innobackupex新增(這個需要留意)

    選擇在 m3320備份實例,備份結束后apply log。
1 innobackupex --datadir=/data/mysql/mysql3320/data/ --user=root --password=ycf.com --no-timestamp --socket=/tmp/mysql3320.sock /data/backup3320
2 innobackupex --apply-log /data/backup3320
    第一次啟動數據庫時,報錯,找不到relay log文件,因為拷貝過來的時候 ,備份庫指定參數如下,mysql庫中的master_relay_log_info指定了relay log的相關信息,但是現在沒有找到文件,數據庫會自動創建 applier跟recovery系列文件。
master_info_repository=TABLE
relay_log_info_repository=TABLE
 
    所以需要進入數據庫中, truncate 兩個表格:mysql.slave_master_info, mysql.slave_relay_log_info ,然后刪除 applier跟recovery系列文件 。
1 truncate table mysql.slave_master_info
2 truncate table mysql.slave_relay_log_info
3  
4 rm -rf applier系列文件
5 rm -rf recovery系列文件
查看下備份的GTID集合,如下
 
重啟數據庫服務,進入數據庫,重新配置GTID集合與備份中的一致,啟動GROUP_REPLICATION。
RESET MASTER;
SET @@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-10';
CHANGE MASTER
TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;

5.1.6 新增從庫:mysqldump新增(這個需要留意)

備份數據庫實例:
/usr/local/mysql5717/bin/mysqldump --socket=/tmp/mysql3320.sock -uroot -p --all-databases > ~/mysql3320.sql
 
    這里有個小TIPS,個人建議,建立一個新的實例后,在新實例中安裝 好 group_replication 引擎,不要等到source后再安裝,這樣的好處是:避免直接在恢復的數據庫實例上安裝引擎,會出現各種錯誤。
 
    在服務器上先安裝 group_replication引擎,然后再source數據,避免source數據后由於環境問題導致group_replication引擎安裝有問題
INSTALL PLUGIN group_replication SONAME 'group_replication.so';
 
    成功后source /data/mysql3320.sql
    檢查當前的binlog跟gtid使用情況,show master status;
    由於目前的使用情況跟mysqldump中的 gtid_purge不一致,重新拷貝下mysql3320.sql中的 gtid_purged語句,注意,如果當前的gtid_excuted不為空,則需要重置下master相關信息,reset master后執行gtid_purge語句。
 
SET @@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-18'; #看GTID集合是否一致
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

5.2 多主模式

5.2.1 單主模式切換多主模式

這部分參考第三部分的第二節,多主模式。
簡要步驟:
1 先由 從主庫開始,逐一逐一停止group replication
2 設置group_replication_single_primary_mode 關閉
3 依次啟動GROUP replication
 
測試內容:
1 整個GROUP中每個SERVER同時執行一個DML語句
2 整個GROUP中每個SERVER同時執行一個DDL語句
 
測試結論:
    嚴重注意,如果在同時提交DDL語句,則在每個實例都是可以提交成功,但是同步到各個實例的時候會發生報錯,group_replication出現 error錯誤,所有實例啟動super_read_only只讀情況,整個group不提供 寫操作,需要人為接入修復。所以DDL語句,建議在設計的時候,就專門只有一個實例可以執行DDL語句,人為默認在某一台上執行DDL語句,而不是每台都執行,避免不必要的沖突。

5.2.2 宕機一台整體影響

kill 進程,其他實例檢車鏈接有問題后,剔除該節點,正常操作。 

5.2.3 宕機后重新加入

啟動數據庫實例后,記得檢查 group_replication_single_primary_mode是否是關閉狀態,如果不是,注意啟動,要不然會由於模式不一致報錯,
set global group_replication_single_primary_mode=OFF;
 
正常執行 
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery';
START GROUP_REPLICATION;

5.2.4 宕機超過合理個數,整體影響(非一個個慢慢宕機,而是一口氣宕機超過合理個數)

    5台server端,一口氣停機了3台,則3台的status修改為UNREACHABLE,剩下的2台為ONLINE,雖然super_read_only是關閉的狀態,但是這兩台server不提供寫功能,僅提供讀功能。
    這里注意下,如果這個時候,發生DML操作,則會掛起該操作,一直處於等待狀態,其他鏈接可以正常連接數據庫進行操作;但是如果發生DDL操作,這個時候,不僅該會話處於等待狀態,而且其他新的連接將無法執行user dbname(涉及操作的DBname)進入到該數據庫中進行 任何查詢操作,但是可以在其他數據庫上 使用 dbname.tbname 方式查詢,比如select * from dbgroup.alld!
 
    僅剩下的一台主庫居然不提供讀寫,除非關閉stop group_replication!
 
    關閉后,error log中會提示事務回滾信息。
 

5.2.5 新增DB:innobackupex新增

簡要步驟
  1. 備份后執行apply log
  2. 新建實例,添加plugins引擎
  3. 替換數據目錄
  4. 啟動數據庫
  5. 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
  6. 查看當前的GTID序號是否與 xtrabackup_binlog_info記錄一致,如果不一致,執行 set gtid_purged
  7. 重啟數據庫服務
  8. 檢查group replication配置是否有誤
  9. change master
  10. start group_replication
#部分參考SQL
SET
@@GLOBAL.GTID_PURGED='9ac06b4e-13aa-11e7-a62e-5254004347f9:1-26:1000004'; CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;

5.2.6 新增DB:mysqldump新增

簡要步驟
  1. 新建實例,添加plugins引擎
  2. source 備份文件
  3. 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
  4. 查看當前的GTID序號是否與備份文件前面記錄一致,如果不一致,執行 set gtid_purged
  5. 檢查group replication配置是否有誤
  6. change master
  7. start group_replication

6 問題記錄

1 ip間隔是 逗號

2 不要有分號,本人就這么笨的開始!

3 port是使用端口號 ,非實例端口號

4 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 32538cbf-12fc-11e7-af43-5254004347f9:1-5 > Group transactions: 2236bd6b-12fc-11e7-a706-5254004347f9:1-16

 [ERROR] Plugin group_replication reported: 'This member has more executed transactions than those present in the group. Local transactions: 32538cbf-12fc-11e7-af43-5254004347f9:1-5 > Group transactions: 2236bd6b-12fc-11e7-a706-5254004347f9:1-16,9ac06b4e-13aa-11e7-a62e-5254004347f9:1'

 [ERROR] Plugin group_replication reported: 'The member contains transactions not present in the group. The member will now exit the group.'

[Note] Plugin group_replication reported: 'To force this member into the group you can use the group_replication_allow_local_disjoint_gtids_join option'

  • 解決
    • set global group_replication_allow_local_disjoint_gtids_join=ON;(但是實際上這種方法治標不治本)
    • 建議還是在搭建group_replication的時候,在start group_replication之前,reset master,重置所有binary log,這樣就不會出現各個實例之間的日志超前影響;但是這里要考慮是否影響到舊主從。

5 [ERROR] Plugin group_replication reported: 'Table te does not have any PRIMARY KEY. This is not compatible with Group Replication'

表格需要添加主鍵

6 mysql> insert into ct(id,name) select 2,'b'; ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement 

只讀模式下,不提供寫服務。

7 [ERROR] Plugin group_replication reported: 'Transaction cannot be executed while Group Replication is on ERROR state. Check for errors and restart the plugin'   2017-03-29T15:46:13.619141Z 31 [ERROR] Run function 'before_commit' in plugin 'group_replication' failed 

GROUP出錯了,是否是重復執行沖突了,好好處理下

7  未解決問題

1 可以通過 show slaves status for channel 'group_replication_recovery' 查看recovery通道執行情況,但是怎么看 applier呢?(show slaves status for channel 'group_replication_applier'報錯 )
2 當宕機超過有效個數時,查看replication_applier_status,狀態正常,但是ONLINE的server實際上不提供寫服務,僅提供讀服務,可以通過什么方式快速判斷呢?個人認為是以下判斷,是否有更好的方式?
 
show global variables like 'super%';
SELECT * FROM performance_schema.replication_group_members;
如果super_read_only是啟動的,那么該成員僅提供讀服務;
如果super_read_only是關閉的,並且 replication_group_members 中正常的成員n 滿足 2n+1 > 整個GROUP成員個數,並且該成員的 member state是online,則該成員可提供讀寫服務。
 
3 當宕機超過有效個數時,ONLINE的server僅提供讀服務,如果需要啟動寫服務,目前個人測試結果是只有兩種方案恢復寫服務:當前SERVER,執行stop group_replication;恢復另外的異常SERVER變正常。是否還有其他方式?
 
4 GROUP中剔除一個成員,假設N個節點,一個節點故障,是采用多數投票機制還是全部一致投票機制?
 
參考文檔:
mysql官方在20161212正式發布了group replication版本,官網詳細地址: https://dev.mysql.com/doc/refman/5.7/en/group-replication.html
感謝京東的中文翻譯: http://acmug.net/?p=164 ,某些地方字面直譯,有些不好理解,如果感覺理解有誤,可對照看下英文文檔。 翻譯中文文檔下載地址: http://storage.360buyimg.com/brickhaha/Mysql.pdf
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM