程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> 細細探究MySQL Group Replicaiton — 配置維護故障處理全集,replicagroup

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

編輯:MySQL綜合教程

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


         本文主要描述 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新增

簡要步驟
#部分參考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新增

簡要步驟

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  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved