1,關於MySQL Group Replication
基於組的復制(Group-basedReplication)是一種被使用在容錯系統中的技術。Replication-group(復制組)是由能夠相互通信的多個服務器(節點)組成的。
在通信層,Groupreplication實現了一系列的機制:比如原子消息(atomicmessage delivery)和全序化消息(totalorderingof messages)。
這些原子化,抽象化的機制,為實現更先進的數據庫復制方案提供了強有力的支持。
MySQL Group Replication正是基於這些技術和概念,實現了一種多主全更新的復制協議。
簡而言之,一個Replication-group就是一組節點,每個節點都可以獨立執行事務,而讀寫事務則會在於group內的其他節點進行協調之后再commit。
因此,當一個事務准備提交時,會自動在group內進行原子性的廣播,告知其他節點變更了什么內容/執行了什么事務。
這種原子廣播的方式,使得這個事務在每一個節點上都保持着同樣順序。
這意味着每一個節點都以同樣的順序,接收到了同樣的事務日志,所以每一個節點以同樣的順序重演了這些事務日志,最終整個group保持了完全一致的狀態。
然而,不同的節點上執行的事務之間有可能存在資源爭用。這種現象容易出現在兩個不同的並發事務上。
假設在不同的節點上有兩個並發事務,更新了同一行數據,那么就會發生資源爭用。
面對這種情況,GroupReplication判定先提交的事務為有效事務,會在整個group里面重演,后提交的事務會直接中斷,或者回滾,最后丟棄掉。
因此,這也是一個無共享的復制方案,每一個節點都保存了完整的數據副本。看如下圖片01.png,描述了具體的工作流程,能夠簡潔的和其他方案進行對比。這個復制方案,在某種程度上,和數據庫狀態機(DBSM)的Replication方法比較類似。
MGR的限制
僅支持InnoDB表,並且每張表一定要有一個主鍵,用於做write set的沖突檢測;
必須打開GTID特性,二進制日志格式必須設置為ROW,用於選主與write set
COMMIT可能會導致失敗,類似於快照事務隔離級別的失敗場景
目前一個MGR集群最多支持9個節點
不支持外鍵於save point特性,無法做全局間的約束檢測與部分部分回滾
二進制日志不支持binlog event checksum
2,安裝mysql 5.7.18
在三台db服務器上面設置/etc/hosts映射,如下:
192.168.1.20 mgr1
192.168.1.21 mgr2
192.168.1.22 mgr3
安裝的數據庫服務器:
數據庫服務器地址 |
端口 |
數據目錄 |
Server-id |
192.168.1.20(mgr1) |
3306 |
/usr/local/mysql/data |
20 |
192.168.1.21(mgr2) |
3306 |
/usr/local/mysql/data |
21 |
192.168.1.22(mgr3) |
3306 |
/usr/local/mysql/data |
22 |
安裝過程略。。。。。
my.cnf的詳細配置
[client] port = 3306 socket = /usr/local/mysql/tmp/mysql.sock [mysqld] port = 3306 socket = /usr/local/mysql/tmp/mysql.sock back_log = 80 basedir = /usr/local/mysql tmpdir = /tmp datadir = /usr/local/mysql/data #-------------------gobal variables------------# gtid_mode = ON enforce_gtid_consistency = ON master_info_repository = TABLE relay_log_info_repository = TABLE binlog_checksum = NONE log_slave_updates = ON log-bin = /usr/local/mysql/log/mysql-bin transaction_write_set_extraction = XXHASH64 loose-group_replication_group_name = 'ce9be252-2b71-11e6-b8f4-00212844f856' loose-group_replication_start_on_boot = off loose-group_replication_local_address = '192.168.1.20:33061' loose-group_replication_group_seeds ='192.168.1.20:33061,192.168.1.21:33061,192.168.1.22:33061' loose-group_replication_bootstrap_group = off max_connect_errors = 20000 max_connections = 2000 wait_timeout = 3600 interactive_timeout = 3600 net_read_timeout = 3600 net_write_timeout = 3600 table_open_cache = 1024 table_definition_cache = 1024 thread_cache_size = 512 open_files_limit = 10000 character-set-server = utf8 collation-server = utf8_bin skip_external_locking performance_schema = 1 user = mysql myisam_recover_options = DEFAULT skip-name-resolve local_infile = 0 lower_case_table_names = 0 #--------------------innoDB------------# innodb_buffer_pool_size = 2000M innodb_data_file_path = ibdata1:200M:autoextend innodb_flush_log_at_trx_commit = 1 innodb_io_capacity = 600 innodb_lock_wait_timeout = 120 innodb_log_buffer_size = 8M innodb_log_file_size = 200M innodb_log_files_in_group = 3 innodb_max_dirty_pages_pct = 85 innodb_read_io_threads = 8 innodb_write_io_threads = 8 innodb_support_xa = 1 innodb_thread_concurrency = 32 innodb_file_per_table innodb_rollback_on_timeout #------------session variables-------# join_buffer_size = 8M key_buffer_size = 256M bulk_insert_buffer_size = 8M max_heap_table_size = 96M tmp_table_size = 96M read_buffer_size = 8M sort_buffer_size = 2M max_allowed_packet = 64M read_rnd_buffer_size = 32M #------------MySQL Log----------------# log-bin = my3306-bin binlog_format = row sync_binlog = 1 expire_logs_days = 15 max_binlog_cache_size = 128M max_binlog_size = 500M binlog_cache_size = 64k slow_query_log log-slow-admin-statements log_warnings = 1 long_query_time = 0.25 #---------------replicate--------------# relay-log-index = relay3306.index relay-log = relay3306 server-id = 20 init_slave = 'set sql_mode=STRICT_ALL_TABLES' log-slave-updates [myisamchk] key_buffer = 512M sort_buffer_size = 512M read_buffer = 8M write_buffer = 8M [mysqlhotcopy] interactive-timeout [mysqld_safe] open-files-limit = 8192 log-error = /usr/local/mysql/log/mysqld_error.log
注意每個節點的server_id、loose-group_replication_local_address、loose-group_replication_group_seeds都配置成自己的相印的參數
3,創建復制環境
在mgr1/mgr2/mgr3上建立復制賬號:
mysql> GRANT REPLICATION SLAVE ON *.* TO 'repl'@'192.168.%' IDENTIFIED BY 'repl';
4,安裝group replication插件
在mgr1、mgr2、mgr3上依次安裝group replication插件
mysql> INSTALL PLUGIN group_replication SONAME 'group_replication.so';
5,配置group replication參數
確保binlog_format是row格式。
mysql> show variables like 'binlog_format';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| binlog_format | ROW |
+---------------+-------+
1 row in set (0.00 sec)
配置文件配置
(1) mgr1上的my.cnf配置:
server-id=20
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "ce9be252-2b71-11e6-b8f4-00212844f856"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "192.168.1.20:33061"
loose-group_replication_group_seeds = "192.168.1.20:33061,192.168.1.21:33061,192.168.1.22:33061"
loose-group_replication_bootstrap_group = off
loose-group_replication_single_primary_mode = true
loose-group_replication_enforce_update_everywhere_checks = false
server-id=21
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "ce9be252-2b71-11e6-b8f4-00212844f856"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "192.168.1.21:33061"
loose-group_replication_group_seeds = "192.168.1.20:33061,192.168.1.21:33061,192.168.1.22:33061"
loose-group_replication_bootstrap_group = off
loose-group_replication_single_primary_mode = true
loose-group_replication_enforce_update_everywhere_checks = false(3)mgr3上的my.cnf配置:
server-id=22
transaction_write_set_extraction = XXHASH64
loose-group_replication_group_name = "ce9be252-2b71-11e6-b8f4-00212844f856"
loose-group_replication_start_on_boot = off
loose-group_replication_local_address = "192.168.1.22 :33061"
loose-group_replication_group_seeds = "192.168.1.20:33061,192.168.1.21:33061,192.168.1.22:33061"
loose-group_replication_bootstrap_group = off
loose-group_replication_single_primary_mode = true
loose-group_replication_enforce_update_everywhere_checks = false |
配置完后,重啟3個db上的mysql服務
6,啟動mgr集群
開始構建group replication集群,通常操作命令
在mgr1、mgr2、mgr3上依次執行
mysql> CHANGE MASTER TO MASTER_USER='repl', MASTER_PASSWORD='repl' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.02 sec)
Db1上建立基本主庫master庫:
# 設置group_replication_bootstrap_group為ON是為了標示以后加入集群的服務器以這台服務器為基准,以后加入的就不需要設置。
mysql> SET GLOBAL group_replication_bootstrap_group = ON;
Query OK, 0 rows affected (0.00 sec)
mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected (1.03 sec)
mysql> select * from performance_schema.replication_group_members;
Db2上啟動group_replication:
Db2上mysql命令行上執行啟動:
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
mysql> start group_replication;
mysql> select * from performance_schema.replication_group_members;
Db3上啟動group_replication:
-- Db3命令行上執行:
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
mysql> start group_replication;
-- 再去master庫mgr1上,查看group_replication成員,會有mgr3的顯示,而且已經是ONLINE了
mysql> select * from performance_schema.replication_group_members;
最后查看集群狀態,都為ONLINE就表示OK:
mysql> select * from performance_schema.replication_group_members;
7,驗證集群復制功能
查看那個是主節點
mysql> select variable_value from performance_schema.global_status where variable_name="group_replication_primary_member";
在master庫mgr1上建立測試庫mgr1,測試表t1,錄入一條數據
mysql> create database mgr1;
Query OK, 1 row affected (0.00 sec)
mysql> create table mgr1.t1(id int,cn varchar(32));
Query OK, 0 rows affected (0.02 sec)
mysql> insert into t1(id,cn)values(1,'a');
ERROR 3098 (HY000): The table does notcomply with the requirements by an external plugin.
-- # 這里原因是group_replaction環境下面,表必須有主鍵不然不允許往里insert值。所以修改表t1,將id字段設置程主鍵即可。
mysql> alter table t1 add primary key(id);
mysql> insert into t1(id,cn)values(1,'a');
去mgr2/mgr3上可以看到數據已經同步過去
mysql> select * from mgr1.t1;
+----+------+
| id | cn |
+----+------+
| 1| a |
+----+------+
1 row in set (0.00 sec)
然后在mgr2/mgr3上執行inert操作,則拒絕,因為mgr2、mgr3為readonly
mysql> insert into t1 select 2,'b';
ERROR 1290 (HY000): The MySQL server isrunning with the --super-read-only option so it cannot execute this statement
8,問題記錄
8.1問題記錄一
MySQL窗口報錯:
ERROR 3092 (HY000): The server is notconfigured properly to be an active member of the group. Please see moredetails on error log.
后台ERROR LOG報錯:
[ERROR] Plugin group_replication reported:'This member has more executed transactions than those present in the group.Local transactions: f16f7f74-c283-11e6-ae37-fa163ee40410:1 > Grouptransactions: 3c992270-c282-11e6-93bf-fa163ee40410:1,
aaaaaa:1-5'
[ERROR]Plugin group_replication reported: 'The member contains transactions notpresent in the group. The member will now exit the group.'
[Note] Plugin group_replication reported: 'Toforce this member into the group you can use the group_replication_allow_local_disjoint_gtids_joinoption'
【解決辦法】:
根據提示打開group_replication_allow_local_disjoint_gtids_join選項,mysql命令行執行:
mysql> set globalgroup_replication_allow_local_disjoint_gtids_join=ON;
再執行開啟組復制:
mysql> start group_replication;
Query OK, 0 rows affected (7.89 sec)
8.2 問題記錄二RECOVERING
在mgr1上查詢集群組成員
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
| group_replication_applier | 3d872c2e-d670-11e6-ac1f-b8ca3af6e36c | | 3306 | ONLINE
| group_replication_applier | ef8ac2de-d671-11e6-9ba4-18a99b763071 | | 3306 | RECOVERING |
| group_replication_applier | fdf2b02e-d66f-11e6-98a8-18a99b76310d | | 3306 | RECOVERING |
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
3 rows in set (0.00 sec)
【解決辦法】:
看報錯[ERROR] Slave I/O for channel'group_replication_recovery': error connecting to master 'repl@:3306'- retry-time: 60 retries: 1, Error_code:2005,連接master庫不上,所以問題在這里,我們賦予的復制賬號是ip的repl@'192.168.%',所以還需要做一個hostname()和mgr1的ip地址192.168.1.20的映射關系。
建立hostname和ip映射
vim /etc/hosts
192.168.1.20 mgr1
192.168.1.21 mgr2
192.168.1.22 mgr3
然后在mgr2上執行如下命令后重新開啟group_replication即可。
mysql> stop group_replication;
Query OK, 0 rows affected (0.02 sec)
mysql> start group_replication;
Query OK, 0 rows affected (5.68 sec)
再去master庫mgr1上,查看group_replication成員,會有mgr2的顯示
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
| CHANNEL_NAME | MEMBER_ID | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
| group_replication_applier | 3d872c2e-d670-11e6-ac1f-b8ca3af6e36c | | 3306 | ONLINE
| group_replication_applier | fdf2b02e-d66f-11e6-98a8-18a99b76310d | | 3306 | ONLINE |
+---------------------------+--------------------------------------+----------------------+-------------+--------------+
2 rows in set (0.00 sec)
8.3問題記錄三
操作問題
mysql> START GROUP_REPLICATION;
ERROR 3092 (HY000): The server is notconfigured properly to be an active member of the group. Please see moredetails on error log.
【解決辦法】:
mysql> SET GLOBALgroup_replication_bootstrap_group = ON;
mysql> START GROUP_REPLICATION;
9,日常維護步驟:
1、如果從庫某一節點關閉
stop group_replication;
2、如果所有的庫都關閉后,第一個庫作為主庫首先執行
set global group_replication_bootstrap_group=ON;
start group_replication;
剩下的庫直接執行即可!
start group_replication;
3、如果主庫故障,會自動從兩個從庫選出一個主庫,主庫啟動后再次執行如下命令后會變成從庫
start group_replication;
