1 What's Group Replication
- 主庫執行完事務后,同步binlog給從庫,從庫ack反饋接收到binlog,主庫提交commit,反饋給客戶端,釋放會話;
- 主庫執行完事務后,主庫提交commit ,同步binlog給從庫,從庫ack反饋接收到binlog,反饋給客戶端,釋放會話;
- 寫操作集中在MASTER服務器上;
- MASTER宕機后,需要人為選擇新主並重新給其他的slave端執行change master(可自行寫第三方工具實現,但是mysql的復制就是沒提供,所以也算是弊端)
- 多主,在同一個group里邊的所有實例,每一個實例可以執行寫操作,也就是每個實例都執行Read-Write
- 注意一點,多主情況下,當執行一個事務時,需要確保同個組內的每個實例都認可這個事務無沖突異常,才可以commit,如果設置的是單主,其他實例ReadOnly,則不需要進行上面的判斷
- 多主情況下,事務並發沖突問題就凸顯出來了,如何避免呢?數據庫內部有一個認證程序,當不同實例並發對同一行發起修改,在同個組內廣播認可時,會出現並發沖突,那么會按照先執行的提交,后執行的回滾
- 彈性,同個Group Replication中,節點的加入或者移除都是自動調整;如果新加入一個節點,該節點會自動從Group的其他節點同步數據,直到與其他節點一致;如果移除一個節點,那么剩下的實例會自動更新,不再向這個節點廣播事務操作,當然,這里要注意,假設一個Group的節點有n個(max(n)=9,同個Group最多節點數為9),移除或者宕機的節點數應該小於等於 floor((n-1)/2) ,注意是向下取整;如果是單主模式,宕機的是單主,則人為選擇新主后,其他節點也會自動從新主同步數據。
- 更高性能的同步機制

2 配置要求與限制
2.1 數據庫要求
2.1.1 innodb引擎
2.1.2 主鍵
2.1.3 隔離級別
2.1.4 外鍵
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
- master_info_repository
- 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
- 注意通訊端口號的配置,它用於組成員之間的通訊使用
- 請確定當前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 主機名修改
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 設置環境變量
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 建立復制賬號
3.1.4 安裝引擎


3.1.5 配置Group
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;



#實例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)
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或者留言
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+行
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或者留言


在搭建的過程中,也理清了兩個重要通道的使用情況:
- group_replication_applier 通道 提供組內成員向 MASTER 實時同步binlog日志使用,這個通道內IO_thread拉取到的日志存放在 *_apaplier.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上。
- group_replication_recovery 通道 提供 首次加入GROUP或者重新加入GROUP時恢復數據使用,這個通道內 IO_thread拉取到的日志存放在 *_recovery.* 系列文件中,再通過SQL_Thread應用到組內的各個SERVER上,應用結束后,刪除所有 *_recovery.* 系列文件 ,重新建立新的 *_recovery.* 系列文件。
3.2 多主模式(group_replication_single_primary_mode =OFF)
# 動態修復方式 set global group_replication_single_primary_mode=OFF; # 配置文件修改方式 loose-group_replication_single_primary_mode = OFF

3.2.1 業務端連接IP處理
3.2.2 GROUP內成員逐個依次主動退出GROUP
1 #實例A 2 stop group_replication; 3 4 #檢查實例B,C的error log,發現實例A主動退出,group成員刪除實例A


1 #實例B 2 stop group_replication; 3 4 #檢查實例B,C的error log,發現實例A主動退出,group成員刪除實例A

#實例c
stop group_replication;

3.2.3 關閉 group_replication_single_primary_mode參數
#動態修改 #實例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 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 #需要啟動 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情況
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)

4 管理維護
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中的成員有哪些
4.2 單主模式下主庫是哪個

4.3 檢查數據庫是否正常提供讀寫服務
4.4 檢查數據庫是否復制出現問題
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來分別描述。
5.1.2 主庫宕機后,恢復,重新加入group
CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='replforslave' FOR CHANNEL 'group_replication_recovery'; START GROUP_REPLICATION;

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

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




5.1.5 新增從庫:innobackupex新增(這個需要留意)
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
1 truncate table mysql.slave_master_info 2 truncate table mysql.slave_relay_log_info 3 4 rm -rf applier系列文件 5 rm -rf recovery系列文件

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新增(這個需要留意)


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 單主模式切換多主模式
5.2.2 宕機一台整體影響

5.2.3 宕機后重新加入
5.2.4 宕機超過合理個數,整體影響(非一個個慢慢宕機,而是一口氣宕機超過合理個數)
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 不要有分號,本人就這么笨的開始!
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: '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出錯了,是否是重復執行沖突了,好好處理下