本文主要描述 MySQL Group Replication的簡易原理、搭建過程以及故障維護管理內容。因爲是新技術,未在生產環境使用過,本文均是虛擬機測試,可能存在考慮不周跟思路有誤狀況,歡迎交流指正。
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的配置狀況。
html
- 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僅提供讀服務。
在搭建的過程當中,也理清了兩個重要通道的使用狀況:mysql
- 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來分別描述。sql
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新增
簡要步驟
- 備份後執行apply log
- 新建實例,添加plugins引擎
- 替換數據目錄
- 啓動數據庫
- 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
- 查看當前的GTID序號是否與 xtrabackup_binlog_info記錄一致,若是不一致,執行 set gtid_purged
- 重啓數據庫服務
- 檢查group replication配置是否有誤
- change master
- 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新增
簡要步驟
- 新建實例,添加plugins引擎
- source 備份文件
- 清理relay-log文件,清理slave_master_info跟slave_relay_log_info信息
- 查看當前的GTID序號是否與備份文件前面記錄一致,若是不一致,執行 set gtid_purged
- 檢查group replication配置是否有誤
- change master
- start group_replication
6 問題記錄
1 ip間隔是 逗號數據庫
2 不要有分號,本人就這麼笨的開始!bootstrap
3 port是使用端口號 ,非實例端口號vim
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個節點,一個節點故障,是採用多數投票機制仍是所有一致投票機制?
參考文檔: