Centos7.5基於MySQL5.7的 InnoDB Cluster 多節點高可用叢集環境部署記錄

散盡浮華發表於2019-03-03

 

一.   MySQL InnoDB Cluster 介紹
MySQL的高可用架構無論是社群還是官方,一直在技術上進行探索,這麼多年提出了多種解決方案,比如MMM, MHA, NDB Cluster, Galera Cluster, InnoDB Cluster, 騰訊的PhxSQL, MySQL Fabric., aliSQL。MySQL官方在2017年4月推出了一套完整的、高可用的Mysql解決方案 - MySQL InnoDB Cluster, 即一組MySQL伺服器可以配置為一個MySQL叢集。在預設的單主節點模式下,叢集伺服器具有一個讀寫主節點和多個只讀輔節點。輔助伺服器是主伺服器的副本。客戶端應用程式通過MySQL Router連線到主服務程式。如果主服務連線失敗,則次要的節點自動提升為主節點,MySQL Router請求到新的主節點。InnoDB Cluster不提供NDB Cluster支援。

->   分散式MySQL之InnoDB和NDB
分散式MySQL主要有InnoDB和NDB模式, NDB是基於叢集的引擎-資料被自動切分並複製到數個機器上(資料節點), 適合於那些需要極高查詢效能和高可用性的應用, 原來是為愛立信的電信應用設計的。 NDB提供了高達99.999%的可靠性,在讀操作多的應用中表現優異。 對於有很多併發寫操作的應用, 還是推薦用InnoDB。

========== NDB和InnoDB儲存引擎之間的特性差異 ==========
InnoDB(MySQL 5.7)特性:
-  InnoDB版本:InnoDB 5.7.20;
-  NDB Cluster版本:不支援;
-  最大儲存長度:64TB;
-  事物:所有標準事物型別;
-  多版本併發控制:支援;
-  資料壓縮:支援;
-  大行支:VARBINARY、VARCHAR、BLOB;
-  同步支援:半同步、非同步;
-  塊讀取:支援;
-  塊寫入:需要使用水平分割槽;
-  高可用性:高;

NDB 7.5/7.6特性:
-  InnoDB版本:InnoDB 5.7.20;
-  NDB Cluster版本: NDB 7.5.8/7.6.4;
-  最大儲存長度:128TB;
-  事物:讀提交;
-  多版本併發控制:不支援;
-  資料壓縮支援:不支援;
-  大行支援:BLOB、 TEXT;
-  同步支援半:自動同步;
-  塊讀取:支援;
-  塊寫入:支援;
-  高可用性:非常高;

->   Mysql InnoDB Cluster 工作原理和流程
MySQL InnoDB叢集提供了一個整合的,本地的,HA解決方案。Mysq Innodb Cluster是利用組複製的 pxos 協議,保障資料一致性,組複製支援單主模式和多主模式。

MySQL InnoDB叢集由以下幾部分組成:
-   MySQL Servers with Group Replication:向叢集的所有成員複製資料,同時提供容錯、自動故障轉移和彈性。MySQL Server 5.7.17或更高的版本。
-   MySQL Router:確保客戶端請求是負載平衡的,並在任何資料庫故障時路由到正確的伺服器。MySQL Router 2.1.3或更高的版本。
-   MySQL Shell:通過內建的管理API建立及管理Innodb叢集。MySQL Shell 1.0.9或更高的版本。

各個元件的關係和工作流程如下:

圖一

圖二

圖三

->   MySQL InnoDB Cluster 叢集特性, 有什麼好處 (為什麼使用它)

-   整合易用
MySQL InnoDB叢集緊密整合了MySQL Servers with Group Replication,MySQL Router,和MySQL Shell,所以不必依賴於外部工具,指令碼或其他部件。 另外它利用了現有的MySQL特性,如:InnoDB, GTIDs, binary logs, multi-threaded slave execution, multi-source replication and Performance Schema。可以在五分鐘內利用MySQL Shell中的指令碼化的管理API來建立及管理MySQL叢集。

-  使用組複製的mysql server HA
組複製提供了內建的組成員管理、資料一致性保證、衝突檢測和處理、節點故障檢測和資料庫故障轉移相關操作的本地高可用性,無需人工干預或自定義工具。組複製同時實現了帶自動選主的單主模式及任意更新的多主模式。通過使用一個強大的新的組通訊系統,它提供了流行的Paxos演算法的內部實現,來自動協調資料複製、一致性、membership。這提供了使MySQL資料庫高度可用所需的所有內建機制。

-  彈性
通過組複製,一組伺服器協調在一起形成一個組。組成員是動態的,伺服器可以自願或強制的地離開及隨時加入。組將根據需要自動重新配置自己,並確保任何加入成員與組同步。這樣就可以方便地在需要時快速地調整資料庫的總容量。

-  故障檢測
組複製實現了一個分散式故障檢測器來查詢並報告failed或不再參與組的伺服器,組中剩餘成員將重新配置。

-  容錯
組複製基於流行的Paxos分散式演算法來提供伺服器之間的分散式協調。為了使一個小組繼續發揮作用,它要求大多數成員線上,並就每一個變化達成協議。這允許MySQL資料庫在發生故障時安全地繼續操作,而無需人工干預,不存在資料丟失或資料損壞的風險。

-  自愈
如果一個伺服器加入該組,它將自動將其狀態與現有成員同步。如果伺服器離開該組,例如它被取下來進行維護,剩下的伺服器將看到它已離開,並將自動重新配置組。當伺服器後重新加入組,它會自動重新與組同步。

-  監測
MySQL Enterprise Monitor 3.4及以後的版本全面支援組複製;監控每個節點的配置,健康,和效能。並且提供最佳實踐建議和提醒,以及易於理解的視覺化工具,允許您輕鬆地監控和管理您的組複製和InnoDB叢集。

-  通過MySQL Router為mysql客戶機應用程式實現HA
MySQL的路由器允許您輕鬆遷移您的獨立的MySQL例項到本地分散式高可用叢集而不影響現有的應用程式。新metadata_cache外掛為Innodb 叢集提供了透明的客戶端連線路由、負載平衡和故障轉移的能力。

-  簡單易用的MySQL shell
MySQL Shell為所有MySQL相關的任務提供了一個直觀、靈活、功能強大的介面。
新的adminapi使得它很容易用一種自我描述的自然語言來建立,監控和管理包括MySQL Router在內的MySQL InnoDB叢集,而不需要了解低層次的概念,配置選項,或其他複雜的方面。

二. Centos7.5 基於MySQL5.7 的 InnoDB Cluster 高可用環境部署記錄 

下面部署採用InnoDB Cluster, 每臺伺服器例項都執行MySQL Group Replication (即冗餘複製機制,內建failover), MGR有兩種模式,一種是Single-Primary,一種是Multi-Primary,即單主或者多主。

需求注意模式Multi-Primary中,所有的節點都是主節點,都可以同時被讀寫,看上去這似乎更好,但是因為多主的複雜性,在功能上如果設定了多主模式,則會有一些使用的限制,比如不支援Foreign Keys with Cascading Constraints。

2.1  環境準備
這裡準備了4臺centos7版本的伺服器用來部署innodb cluster多節點叢集環境 (至少也要需要3臺伺服器), 其中:
1) db-node01、db-node02、db-node03 作為 cluster 節點伺服器, 三個節點都要安裝 mysql8.0.x 與 mysql-shell
2) db-route01 作為管理節點伺服器,用來負責建立 cluster,並作為 cluster 的路由, 該節點需要安裝mysql-shell、mysql-router
3) 所有節點的python版本要在2.7以上

ip地址                主機名          角色               安裝軟體
172.16.60.211        db-node01      cluster節點1       Mysql5.7, mysql-shell
172.16.60.212        db-node02      cluster節點2       Mysql5.7, mysql-shell
172.16.60.213        db-node03      cluster節點3       Mysql5.7, mysql-shell
172.16.60.214        db-route01     管理節點1          mysql-shell, mysql-route
   
[root@db-node01 ~]# cat /etc/redhat-release
CentOS Linux release 7.5.1804 (Core)
   
[root@db-node01 ~]# python -V
Python 2.7.5
   
為了方便實驗,關閉所有節點的防火牆
[root@MGR-node1 ~]# systemctl stop firewalld
[root@MGR-node1 ~]# firewall-cmd --state
not running
   
關閉每個節點的selinux
[root@MGR-node1 ~]# cat /etc/sysconfig/selinux |grep "SELINUX=disabled"
SELINUX=disabled
[root@MGR-node1 ~]# setenforce 0        
setenforce: SELinux is disabled
[root@MGR-node1 ~]# getenforce          
Disabled
   
配置每個節點的/etc/hosts主機對映, 方便通過節點的hostname進行連線
這一步很重要,否則可能會出現無法同步的情況,因為資料庫需要根據member_host同步,如果不配置,預設就是localhost,這樣時無法通訊的!!!
[root@db-node01 ~]# vim /etc/hosts
...........
172.16.60.211    db-node01
172.16.60.212    db-node02
172.16.60.213    db-node03
172.16.60.214    db-route01
  
所有節點進行如下的相關優化配置
[root@db-node01 ~]# cat>>/etc/sysctl.conf <<EOF
fs.aio-max-nr = 1048576
fs.file-max = 681574400
kernel.shmmax = 137438953472
kernel.shmmni = 4096
kernel.sem = 250 32000 100 200
net.ipv4.ip_local_port_range = 9000 65000
net.core.rmem_default = 262144
net.core.rmem_max = 4194304
net.core.wmem_default = 262144
net.core.wmem_max = 1048586
EOF
  
[root@db-node01 ~]# sysctl -p
  
[root@db-node01 ~]# cat>>/etc/security/limits.conf <<EOF
mysql soft nproc 65536
mysql hard nproc 65536
mysql soft nofile 65536
mysql hard nofile 65536
EOF
  
[root@db-node01 ~]# cat>>/etc/pam.d/login <<EOF
session required /lib/security/pam_limits.so
session required pam_limits.so
EOF
  
[root@db-node01 ~]# cat>>/etc/profile<<EOF
if [ $USER = "mysql" ]; then
ulimit -u 16384 -n 65536
fi
EOF
  
[root@db-node01 ~]# source /etc/profile

==========================================================
mysql-shell下載地址: https://pan.baidu.com/s/1nPWcmKb2T_iDmpQ84ZrVmQ     提取密碼: u425
mysql-route下載地址: https://pan.baidu.com/s/1Tb7lxnxyiFdwxkdKOlU29Q     提取密碼: sq6h

2.2   在管理節點安裝mysql shell 和 mysql-route

[root@db-route01 ~]# cd /usr/local/src/
[root@db-route01 src]# ll
total 21648
-rw-rw-r-- 1 root root 15526654 Mar  8 16:08 mysql-router-2.1.4-linux-glibc2.12-x86-64bit.tar.gz
-rw-rw-r-- 1 root root  6635831 Mar 22  2017 mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz

[root@db-route01 src]# tar -zvxf mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz 
[root@db-route01 src]# tar -zvxf mysql-router-2.1.4-linux-glibc2.12-x86-64bit.tar.gz 

[root@db-route01 src]# mv mysql-router-2.1.4-linux-glibc2.12-x86-64bit mysql-route
[root@db-route01 src]# mv mysql-shell-1.0.9-linux-glibc2.12-x86-64bit mysql-shell
[root@db-route01 src]# mv mysql-route /usr/local/
[root@db-route01 src]# mv mysql-shell /usr/local/

[root@db-route01 src]# vim /etc/profile
..............
export PATH=$PATH:/usr/local/mysql-shell/bin/:/usr/local/mysql-route/bin/

[root@db-route01 src]# source /etc/profile

[root@db-route01 ~]# mysqlprovision --version
mysqlprovision version 2.0.0

[root@db-route01 ~]# mysqlsh --version
MySQL Shell Version 1.0.9

[root@db-route01 ~]# mysqlrouter --version
MySQL Router v2.1.4 on Linux (64-bit) (GPL community edition)

2.3  在三個cluster節點安裝和部署Mysql5.7及 mysql-shell

1) 安裝mysql-shell  (三個節點同樣操作)
[root@db-node01 ~]# cd /usr/local/src/
[root@db-node01 src]# ll mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz 
-rw-r--r-- 1 root root 6635831 Mar 22  2017 mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz

[root@db-node01 src]# tar -zvxf mysql-shell-1.0.9-linux-glibc2.12-x86-64bit.tar.gz
[root@db-node01 src]# mv mysql-shell-1.0.9-linux-glibc2.12-x86-64bit mysql-shell
[root@db-node01 src]# mv mysql-shell /usr/local/

[root@db-node01 src]# echo "export PATH=$PATH:/usr/local/mysql-shell/bin/" >> /etc/profile
[root@db-node01 src]# source /etc/profile

[root@db-node01 ~]# mysqlprovision --version                           
mysqlprovision version 2.0.0

[root@db-node01 ~]# mysqlsh --version       
MySQL Shell Version 1.0.9

2) 安裝mysql5.7  (三個節點同樣操作)
使用yum方式安裝Mysql5.7,參考:https://www.cnblogs.com/kevingrace/p/8340690.html

安裝MySQL yum資源庫
[root@db-node01 ~]# yum localinstall https://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
    
安裝MySQL 5.7
[root@db-node01 ~]# yum install -y mysql-community-server
    
啟動MySQL伺服器和MySQL的自動啟動
[root@db-node01 ~]# systemctl start mysqld.service
[root@db-node01 ~]# systemctl enable mysqld.service
    
設定登入密碼
由於MySQL從5.7開始不允許首次安裝後使用空密碼進行登入!為了加強安全性,系統會隨機生成一個密碼以供管理員首次登入使用,
這個密碼記錄在/var/log/mysqld.log檔案中,使用下面的命令可以檢視此密碼:
[root@db-node01 ~]# cat /var/log/mysqld.log|grep 'A temporary password'
2019-01-11T05:53:17.824073Z 1 [Note] A temporary password is generated for root@localhost: TaN.k:*Qw2xs
    
使用上面檢視的密碼TaN.k:*Qw2xs 登入mysql,並重置密碼為123456
[root@db-node01 ~]# mysql -p                 #輸入預設的密碼:TaN.k:*Qw2xs
.............
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)
    
mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)
    
mysql> set password=password("123456");
Query OK, 0 rows affected, 1 warning (0.00 sec)
    
mysql> flush privileges;
Query OK, 0 rows affected (0.00 sec)
    
檢視mysql版本
[root@db-node01 ~]# mysql -p123456
........
mysql> select version();
+-----------+
| version() |
+-----------+
| 5.7.24    |
+-----------+
1 row in set (0.00 sec)
   
=====================================================================
溫馨提示
mysql5.7通過上面預設安裝後,執行語句可能會報錯:
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements
   
這個報錯與Mysql 密碼安全策略validate_password_policy的值有關,validate_password_policy可以取0、1、2三個值:
解決辦法:
set global validate_password_policy=0;
set global validate_password_length=1;

3) 配置my.cnf

先配置db-node01節點的my.cnf
[root@db-node01 ~]# cp /etc/my.cnf /etc/my.cnf.bak
[root@db-node01 ~]# >/etc/my.cnf
[root@db-node01 ~]# vim /etc/my.cnf
[mysqld]
datadir = /var/lib/mysql
socket = /var/lib/mysql/mysql.sock
         
symbolic-links = 0
         
log-error = /var/log/mysqld.log
pid-file = /var/run/mysqld/mysqld.pid
 
#複製框架
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
 
log_bin=binlog
log_slave_updates=ON
binlog_format=ROW
master_info_repository=TABLE
relay_log_info_repository=TABLE
 
#組複製設定
#server必須為每個事務收集寫集合,並使用XXHASH64雜湊演算法將其編碼為雜湊
transaction_write_set_extraction=XXHASH64
#告知外掛加入或建立組命名,UUID
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
#server啟動時不自啟組複製,為了避免每次啟動自動引導具有相同名稱的第二個組,所以設定為OFF。
loose-group_replication_start_on_boot=off
#告訴外掛使用IP地址,埠24901用於接收組中其他成員轉入連線
loose-group_replication_local_address="172.16.60.211:24901"
#啟動組server,種子server,加入組應該連線這些的ip和埠;其他server要加入組得由組成員同意
loose-group_replication_group_seeds="172.16.60.211:24901,172.16.60.212:24901,172.16.60.213:24901"
loose-group_replication_bootstrap_group=off
# 使用MGR的單主模式
loose-group_replication_single_primary_mode = on  
disabled_storage_engines = MyISAM,BLACKHOLE,FEDERATED,CSV,ARCHIVE
report_port=3306

如上配置完成後, 將db-node01節點的/etc/my.cnf檔案拷貝到其他兩個節點
[root@db-node01 ~]# rsync -e "ssh -p22" -avpgolr /etc/my.cnf root@172.16.60.212:/etc/
[root@db-node01 ~]# rsync -e "ssh -p22" -avpgolr /etc/my.cnf root@172.16.60.213:/etc/

3個cluster節點除了server_id、loose-group_replication_local_address 兩個引數不一樣外,其他保持一致。
所以待拷貝完成後, 分別修改db-node02和db-node03節點/etc/my.cnf檔案的server_id、loose-group_replication_local_address兩個引數

配置完成後, 要依次重啟三個節點的資料庫,安裝MGR外掛,設定複製賬號(所有MGR節點都要執行)
[root@db-node01 ~]# systemctl restart mysqld

2.4  建立Innodb Cluster叢集

1) 在 db-node01 上建立叢集,通過 db-node01 上的 shell 連線db-node01 的 mysql
[root@db-node01 ~]# mysqlsh
...................
# 執行配置命令,也需要密碼
# 然後需要輸入MySQL配置檔案路徑,本示例中的路徑是 /usr/local/data/s1/s1.cnf
# 接下來需要建立供其他主機訪問的使用者,這裡選擇第1項,為root使用者授權

mysql-js> shell.connect('root@localhost:3306');
Please provide the password for 'root@localhost:3306':               #輸入密碼123456
Creating a Session to 'root@localhost:3306'
Classic Session successfully established. No default schema selected.

mysql-js> dba.configureLocalInstance();
Please provide the password for 'root@localhost:3306':               #輸入密碼123456

Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [Y|n]:                                           #直接回車, 使用預設的/etc/my.cnf配置檔案
MySQL user 'root' cannot be verified to have access to other hosts in the network.

1) Create root@% with necessary grants
2) Create account with different name
3) Continue without creating account
4) Cancel
Please select an option [1]: 1                         #選擇第1項,為root使用者授權, 建立供其他主機訪問的使用者
Password for new account:                             #輸入供其他主機訪問的使用者root使用者授權的密碼. 這裡依然設定123456
Confirm password: 
Validating instance...

Dba.configureLocalInstance: Your password does not satisfy the current policy requirements (MySQL Error 1819)

出現上面報錯的解決辦法:
開啟另一個終端視窗, 登入db-node01節點的mysql,執行下面命令:
[root@db-node01 ~]# mysql -p123456
.................
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

然後接著上面db-node01終端視窗的mysql-shell繼續執行:
mysql-js> shell.connect('root@localhost:3306');
Please provide the password for 'root@localhost:3306':            #輸入密碼123456
Creating a Session to 'root@localhost:3306'
Classic Session successfully established. No default schema selected.

mysql-js> dba.configureLocalInstance();
Please provide the password for 'root@localhost:3306':           #輸入密碼123456

Detecting the configuration file...
Found configuration file at standard location: /etc/my.cnf
Do you want to modify this file? [Y|n]:                                       #直接回車, 使用預設的/etc/my.cnf配置檔案
MySQL user 'root' cannot be verified to have access to other hosts in the network.

1) Create root@% with necessary grants
2) Create account with different name
3) Continue without creating account
4) Cancel
Please select an option [1]: 1                     # 選擇第1項,為root使用者授權, 即供其他主機訪問的使用者root使用者授權的密碼, 否則其他機器使用root使用者連線不上不本機的mysql
Password for new account:                         #輸入. 這裡依然設定123456. 這裡授權之後, 登入db-node01節點的mysql, 執行"select host, user from mysql.user" 命令就能發現
Confirm password: 
Validating instance...

The instance 'localhost:3306' is valid for Cluster usage
You can now use it in an InnoDB Cluster.

{
    "status": "ok"
}
mysql-js> 

由上面的資訊看出, status 為 ok 說明配置沒問題了,可以用來建立cluster

2) 通過 db-route01 的 mysql-shell 連線 node01 建立 cluster
[root@db-route01 ~]# mysqlsh
................
# 連線db-node01
mysql-js> shell.connect('root@db-node01:3306');                   
Please provide the password for 'root@db-node01:3306':         #輸入密碼123456
Creating a Session to 'root@db-node01:3306'
Classic Session successfully established. No default schema selected.

# 建立一個 cluster,命名為 'myCluster'
mysql-js> var cluster = dba.createCluster('myCluster');
A new InnoDB cluster will be created on instance 'root@db-node01:3306'.

Creating InnoDB cluster 'myCluster' on 'root@db-node01:3306'...
Adding Seed Instance...

Cluster successfully created. Use Cluster.addInstance() to add MySQL instances.
At least 3 instances are needed for the cluster to be able to withstand up to
one server failure.

如上的資訊, 如果建立成功, 則會輸出的資訊中會有類似“Cluster successfully created.”的語句

#建立成功後,檢視cluster狀態
mysql-js> cluster.status();
{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "db-node01:3306", 
        "status": "OK_NO_TOLERANCE", 
        "statusText": "Cluster is NOT tolerant to any failures.", 
        "topology": {
            "db-node01:3306": {
                "address": "db-node01:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }
    }
}

mysql-js> dba.getCluster(); 
<Cluster:myCluster>

注意上面這個db-route01的mysql-shell終端視窗就不要關閉了, 一直保持連線中,也就是一直在當前叢集狀態中, 後面新增其他節點到cluster叢集中會用到! (後面說到常用命令時會解釋)

3) 新增節點 db-node02到上面建立的"myCluster"叢集中
通過db-node02本機 mysql-shell 對 mysql 進行配置
[root@db-node02 ~]# mysqlsh
................
 MySQL  JS > shell.connect('root@localhost:3306');
Creating a session to 'root@localhost:3306'
Please provide the password for 'root@localhost:3306': ******        #輸入密碼123456
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 251
Server version: 5.7.25-log MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
<ClassicSession:root@localhost:3306>

 
  MySQL  localhost:3306 ssl  JS > dba.configureLocalInstance();
Configuring local MySQL instance listening at port 3306 for use in an InnoDB cluster...

This instance reports its own address as 172.16.60.212

WARNING: User 'root' can only connect from localhost.
If you need to manage this instance while connected from other hosts, new account(s) with the proper source address specification must be created.

1) Create remotely usable account for 'root' with same grants and password
2) Create a new admin account for InnoDB cluster with minimal required grants
3) Ignore and continue
4) Cancel

Please select an option [1]: 1
Please provide a source address filter for the account (e.g: 192.168.% or % etc) or leave empty and press Enter to cancel.
Account Host: %                         #選擇%, 表示允許任何機器遠端使用root使用者連線本機的mysql

The instance 'localhost:3306' is valid for InnoDB cluster usage.

Your password does not satisfy the current policy requirements (MySQL Error 1819)

解決辦法:
登入db-node02節點的mysql
[root@db-node02 ~]# mysql -p123456
...............

mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

接著繼續登入db-node02本機的mysql-shell 進行配置
[root@db-node02 ~]# mysqlsh
.............
MySQL  JS > shell.connect('root@localhost:3306');
Creating a session to 'root@localhost:3306'
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 180
Server version: 5.7.25-log MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
<ClassicSession:root@localhost:3306>

 MySQL  localhost:3306 ssl  JS > dba.configureLocalInstance();
Configuring local MySQL instance listening at port 3306 for use in an InnoDB cluster...

This instance reports its own address as db-node02
Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.

WARNING: User 'root' can only connect from localhost.
If you need to manage this instance while connected from other hosts, new account(s) with the proper source address specification must be created.

1) Create remotely usable account for 'root' with same grants and password
2) Create a new admin account for InnoDB cluster with minimal required grants
3) Ignore and continue
4) Cancel

Please select an option [1]: 1
Please provide a source address filter for the account (e.g: 192.168.% or % etc) or leave empty and press Enter to cancel.
Account Host: %

The instance 'localhost:3306' is valid for InnoDB cluster usage.

Cluster admin user 'root'@'%' created.

 MySQL  localhost:3306 ssl  JS > 

 然後登入db-node02節點的mysql, 發現上面使用root使用者遠端連線的授權已經有了
 [root@db-node02 ~]# mysql -p123456
 ..............
mysql> select host,user from mysql.user;
+-----------+---------------+
| host      | user          |
+-----------+---------------+
| %         | root          |
| localhost | mysql.session |
| localhost | mysql.sys     |
| localhost | root          |
+-----------+---------------+
4 rows in set (0.00 sec)


接著修改 my.cnf,新增配置項:
[root@db-node02 ~]# vim /etc/my.cnf
............
loose-group_replication_allow_local_disjoint_gtids_join=on

重啟mysql服務
[root@db-node02 ~]# systemctl restart mysqld

然後通過 db-route01節點 的 mysql-shell 新增 node02 到 "myCluster"叢集中
接著上面的db-route01的mysql-shell終端視窗  (注意這個終端視窗是上面執行後, 沒有關閉一直開著的)

mysql-js> cluster.addInstance('root@db-node02:3306');
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.

Please provide the password for 'root@db-node02:3306': 
Adding instance to the cluster ...

The instance 'root@db-node02:3306' was successfully added to the cluster.

上面資訊表示db-node02節點已經成功新增到"myCluster"叢集中了. 如下檢視叢集狀態
mysql-js> cluster.status();
{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "db-node01:3306", 
        "status": "OK_NO_TOLERANCE", 
        "statusText": "Cluster is NOT tolerant to any failures.", 
        "topology": {
            "db-node01:3306": {
                "address": "db-node01:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "db-node02:3306": {
                "address": "db-node02:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }
    }
}

同樣, 上面操作後, 這個db-route01節點的mysql-shell當前終端視窗不要關閉,繼續保持在叢集狀態中, 下面新增db-node03節點到叢集中會用到這裡.(後面常用命令中會提到)

4) 新增節點 db-node03到上面建立的"myCluster"叢集中
首先登入db-node03節點的mysql
[root@db-node03 ~]# mysql -p123456
............
mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

登入db-node03節點的mysql-shell, 進行配置
[root@db-node03 ~]# mysqlsh
.............
 MySQL  JS > shell.connect('root@localhost:3306');
Creating a session to 'root@localhost:3306'
Please provide the password for 'root@localhost:3306': ******
Save password for 'root@localhost:3306'? [Y]es/[N]o/Ne[v]er (default No): Y
Fetching schema names for autocompletion... Press ^C to stop.
Your MySQL connection id is 393
Server version: 5.7.25-log MySQL Community Server (GPL)
No default schema selected; type \use <schema> to set one.
<ClassicSession:root@localhost:3306>

 MySQL  localhost:3306 ssl  JS > dba.configureLocalInstance();
Configuring local MySQL instance listening at port 3306 for use in an InnoDB cluster...

This instance reports its own address as db-node03
Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.

WARNING: User 'root' can only connect from localhost.
If you need to manage this instance while connected from other hosts, new account(s) with the proper source address specification must be created.

1) Create remotely usable account for 'root' with same grants and password
2) Create a new admin account for InnoDB cluster with minimal required grants
3) Ignore and continue
4) Cancel

Please select an option [1]: 1
Please provide a source address filter for the account (e.g: 192.168.% or % etc) or leave empty and press Enter to cancel.
Account Host: %

The instance 'localhost:3306' is valid for InnoDB cluster usage.

Cluster admin user 'root'@'%' created.

接著修改 my.cnf,新增配置項:
[root@db-node03 ~]# vim /etc/my.cnf
............
loose-group_replication_allow_local_disjoint_gtids_join=on

重啟mysql服務
[root@db-node03 ~]# systemctl restart mysqld

然後通過 db-route01節點 的 mysql-shell 新增 node03 到 "myCluster"叢集中
接著上面的db-route01的mysql-shell終端視窗  (注意這個終端視窗是上面執行後, 沒有關閉一直開著的)

mysql-js> cluster.addInstance('root@db-node03:3306'); 
A new instance will be added to the InnoDB cluster. Depending on the amount of
data on the cluster this might take from a few seconds to several hours.

Please provide the password for 'root@db-node03:3306': 
Adding instance to the cluster ...

The instance 'root@db-node03:3306' was successfully added to the cluster.

上面資訊表示db-node02節點已經成功新增到"myCluster"叢集中了. 如下檢視叢集狀態
mysql-js> cluster.status();
{
    "clusterName": "myCluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "db-node01:3306", 
        "status": "OK", 
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", 
        "topology": {
            "db-node01:3306": {
                "address": "db-node01:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "db-node02:3306": {
                "address": "db-node02:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "db-node03:3306": {
                "address": "db-node03:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }
    }
}

通過上面cluster叢集資訊可知,  db-node01節點是主節點, 具有R/W讀寫許可權, 其他兩個節點是從節點, 具有R/O 只讀許可權

2.5   啟動管理節點的route

進入 db-route01管理節點中mysql-router 安裝目錄,配置並啟動 router 
[root@db-route01 ~]# /usr/local/mysql-route/bin/mysqlrouter --bootstrap root@db-node01:3306 -d myrouter --user=root 
Please enter MySQL password for root: 

Bootstrapping MySQL Router instance at /root/myrouter...
MySQL Router  has now been configured for the InnoDB cluster 'myCluster'.

The following connection information can be used to connect to the cluster.

Classic MySQL protocol connections to cluster 'myCluster':
- Read/Write Connections: localhost:6446             #讀寫埠
- Read/Only Connections: localhost:6447              #只讀埠

X protocol connections to cluster 'myCluster':
- Read/Write Connections: localhost:64460
- Read/Only Connections: localhost:64470

這裡會在當前目錄下產生mysql-router 目錄, 並生成router配置檔案,接著把配置檔案修改一下:
[root@db-route01 ~]# ls /root/myrouter/
data  log  mysqlrouter.conf  mysqlrouter.key  run  start.sh  stop.sh
[root@db-route01 ~]# cat /root/myrouter/mysqlrouter.conf          #可以修改配置檔案, 也可以預設不修改

預設通過route連線mysql後, 6446埠連線後可以進行讀寫操作. 6447埠連線後只能進行只讀操作.

然後啟動mysqlroute
[root@db-route01 ~]# /root/myrouter/start.sh 
PID 16484 written to /root/myrouter/mysqlrouter.pid

[root@db-route01 ~]# ps -ef|grep myroute                  
root     18473     1  0 22:26 pts/1    00:00:00 sudo ROUTER_PID=/root/myrouter/mysqlrouter.pid /usr/local/mysql-route/bin/mysqlrouter -c /root/myrouter/mysqlrouter.conf --user=root
root     18486 18473  0 22:26 pts/1    00:00:00 /usr/local/mysql-route/bin/mysqlrouter -c /root/myrouter/mysqlrouter.conf --user=root
root     18612  5091  0 22:26 pts/1    00:00:00 grep --color=auto myroute

[root@db-route01 ~]# netstat -tunlp|grep 18486
tcp        0      0 0.0.0.0:64460           0.0.0.0:*               LISTEN      18486/mysqlrouter   
tcp        0      0 0.0.0.0:6446            0.0.0.0:*               LISTEN      18486/mysqlrouter   
tcp        0      0 0.0.0.0:6447            0.0.0.0:*               LISTEN      18486/mysqlrouter   
tcp        0      0 0.0.0.0:64470           0.0.0.0:*               LISTEN      18486/mysqlrouter  

這樣就可以使用MySQL客戶端連線router了.  下面驗證下連線router:

a) 管理節點本機mysql-shell連線:
[root@db-route01 ~]# mysqlsh --uri root@localhost:6446

b) 管理節點本機mysql連線:
[root@db-route01 ~]# mysql -u root -h 127.0.0.1 -P 6446 -p

c) 遠端客戶機通過route連線mysql
[root@db-node01 ~]# mysql -u root -h 172.16.60.214 -P 6446 -p

測試cluster節點資料同步. 這裡選擇db-node03節點作為遠端客戶端連線router
[root@db-node03 ~]# mysql -u root -h 172.16.60.214 -P 6446 -p
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1054
Server version: 5.7.25-log MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+-------------------------------+
| Database                      |
+-------------------------------+
| information_schema            |
| mysql                         |
| mysql_innodb_cluster_metadata |
| performance_schema            |
| sys                           |
+-------------------------------+
5 rows in set (0.00 sec)

測試測試庫kevin
mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;  
ERROR 1044 (42000): Access denied for user 'root'@'%' to database 'kevin'

這是因為'root@%'沒有建立庫的許可權
mysql> select host,user from mysql.user;
+-----------+----------------------------------+
| host      | user                             |
+-----------+----------------------------------+
| %         | mysql_innodb_cluster_rp496261783 |
| %         | mysql_innodb_cluster_rp496457975 |
| %         | mysql_innodb_cluster_rp496569258 |
| %         | mysql_innodb_cluster_rp496629685 |
| %         | mysql_router1_olzau3ltjqzx       |
| %         | root                             |
| localhost | mysql.session                    |
| localhost | mysql.sys                        |
| localhost | root                             |
+-----------+----------------------------------+
9 rows in set (0.00 sec)

mysql> show grants for root@'%';
+-----------------------------------------------------------------------------------------------------------------------------------------+
| Grants for root@%                                                                                                                       |
+-----------------------------------------------------------------------------------------------------------------------------------------+
| GRANT RELOAD, SHUTDOWN, PROCESS, FILE, SUPER, REPLICATION SLAVE, REPLICATION CLIENT, CREATE USER ON *.* TO 'root'@'%' WITH GRANT OPTION |
| GRANT SELECT, INSERT, UPDATE, DELETE ON `mysql`.* TO 'root'@'%' WITH GRANT OPTION                                                       |
| GRANT SELECT ON `performance_schema`.* TO 'root'@'%' WITH GRANT OPTION                                                                  |
| GRANT ALL PRIVILEGES ON `mysql_innodb_cluster_metadata`.* TO 'root'@'%' WITH GRANT OPTION                                               |
+-----------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)

登入主庫, 建立一個具有管理權許可權的使用者
[root@db-node01 ~]# mysql -p123456
.............
mysql> set global validate_password_policy=0;
Query OK, 0 rows affected (0.00 sec)

mysql> set global validate_password_length=1;
Query OK, 0 rows affected (0.00 sec)

mysql> grant all on *.* to bobo@'%' identified by "bo@123" with grant option;
Query OK, 0 rows affected, 1 warning (0.05 sec)

接著遠端使用上面建立的新賬號登入router操作
[root@db-node03 ~]# mysql -u bobo -h 172.16.60.214 -P 6446 -p 
........
mysql> show grants for bobo@'%';
+-------------------------------------------------------------+
| Grants for bobo@%                                           |
+-------------------------------------------------------------+
| GRANT ALL PRIVILEGES ON *.* TO 'bobo'@'%' WITH GRANT OPTION |
+-------------------------------------------------------------+
1 row in set (0.00 sec)

測試測試庫kevin
mysql> CREATE DATABASE kevin CHARACTER SET utf8 COLLATE utf8_general_ci;  
Query OK, 1 row affected (0.06 sec)

mysql> use kevin;
Database changed
mysql> create table if not exists haha (id int(10) PRIMARY KEY AUTO_INCREMENT,name varchar(50) NOT NULL);
Query OK, 0 rows affected (0.22 sec)

mysql> insert into kevin.haha values(1,"wangshibo"),(2,"guohuihui"),(3,"yangyang"),(4,"shikui");
Query OK, 4 rows affected (0.13 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from kevin.haha;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | wangshibo |
|  2 | guohuihui |
|  3 | yangyang  |
|  4 | shikui    |
+----+-----------+
4 rows in set (0.00 sec)

分別登入三個cluster節點的mysql, 發現測試庫kevin已經完成同步了, 其中:
寫操作的資料會先寫到db-node01節點, 然後同步到db-node02和db-node03只讀節點上.

注意: 上面使用6446埠連線的route, 可以進行讀寫操作. 但是使用6447埠連線後, 就只能進行只讀操作了. 登入後可以執行" select @@hostname" 檢視登入到哪個節點上.
[root@db-node03 ~]# mysql -u bobo -h 172.16.60.214 -P 6447 -p
.............
mysql> select * from kevin.haha;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | wangshibo |
|  2 | guohuihui |
|  3 | yangyang  |
|  4 | shikui    |
+----+-----------+
4 rows in set (0.00 sec)

mysql> delete from kevin.haha where id>2;
ERROR 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

此外, 還可以利用keepalived實現InnoDB Cluster的高可用, 即兩臺db-route管理節點, 通過VIP資源實現故障無感知切換.  這樣需要準備5臺節點, 其中3個cluster節點(安裝mysql, mysql-shell), 2個route管理節點(安裝keepalived, mysql-shell, mysql-route, mysql-client)

                                                                                  InnoDB Cluster叢集 日常維護命令                                                                        

1) 在各節點配置之後, 建立cluster叢集之前, 可以依次檢查下cluster各個節點是否可用

[root@db-node01 ~]# mysqls
.................
mysql-js> dba.checkInstanceConfiguration("root@localhost:3306")                    
Please provide the password for 'root@localhost:3306': 
Validating instance...

The instance 'localhost:3306' is valid for Cluster usage
{
    "status": "ok"
}

mysql-js> dba.checkInstanceConfiguration("root@db-node02:3306")         
Please provide the password for 'root@db-node02:3306': 
Validating instance...

The instance 'db-node02:3306' is valid for Cluster usage
{
    "status": "ok"
}

mysql-js> dba.checkInstanceConfiguration("root@db-node03:3306") 
Please provide the password for 'root@db-node03:3306': 
Validating instance...

The instance 'db-node03:3306' is valid for Cluster usage
{
    "status": "ok"
}

2) 比如在上面建立Innodb cluster叢集過程中, 再次登入mysqlsh (從客戶端遠端登入, 或任意節點本地登入), 怎麼獲得並檢視叢集狀態

[root@db-node01 ~]# mysqlsh
.................
mysql-js> shell.connect("root@db-node01:3306");
Please provide the password for 'root@db-node01:3306':
Creating a Session to 'root@db-node01:3306'
Classic Session successfully established. No default schema selected.
 
檢視叢集狀態
mysql-js> cluster.status();
ReferenceError: cluster is not defined
 
上面方式檢視, 會報錯說叢集沒有定義, 這時需要先執行下面這條語句之後,才看檢視到叢集狀態!!!!!
mysql-js> cluster.status();
ReferenceError: cluster is not defined
 
然後就可以檢視叢集狀態了
mysql-js> cluster=dba.getCluster();
<Cluster:myCluster>
mysql-js> cluster.status();
{
    "clusterName": "myCluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db-node01:3306",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "db-node01:3306": {
                "address": "db-node01:3306",
                "mode": "R/W",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            },
            "db-node02:3306": {
                "address": "db-node02:3306",
                "mode": "R/O",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            },
            "db-node03:3306": {
                "address": "db-node03:3306",
                "mode": "R/O",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            }
        }
    }
}
 
從遠端客戶端登入
[root@db-node03 ~]# mysqlsh --uri root@172.16.60.214:6446
......................
 MySQL  172.16.60.214:6446 ssl  JS > cluster=dba.getCluster();
<Cluster:myCluster>
 
 MySQL  172.16.60.214:6446 ssl  JS > cluster.status();
{
    "clusterName": "myCluster",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "db-node01:3306",
        "ssl": "REQUIRED",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "db-node01:3306": {
                "address": "db-node01:3306",
                "mode": "R/W",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            },
            "db-node02:3306": {
                "address": "db-node02:3306",
                "mode": "R/O",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            },
            "db-node03:3306": {
                "address": "db-node03:3306",
                "mode": "R/O",
                "readReplicas": {},
                "role": "HA",
                "status": "ONLINE"
            }
        }
    },
    "groupInformationSourceMember": "mysql://root@172.16.60.214:6446"
}
 
檢視已建立的叢集名稱
 MySQL  172.16.60.214:6446 ssl  JS > dba.getCluster();
<Cluster:myCluster>
 
=================================================
總結:
a) dba.getCluster();     #檢視建立的叢集
b) cluster=dba.getCluster();    #獲取當前叢集
c) cluster.status();         #檢視叢集狀態
 
=================================================

3) InnoDB Cluster叢集維護的命令幫助

mysql-js> dba.help();
 
The global variable 'dba' is used to access the MySQL AdminAPI functionality
and perform DBA operations. It is used for managing MySQL InnoDB clusters.
 
The following properties are currently supported.
 
 - verbose Enables verbose mode on the Dba operations.
 
 
The following functions are currently supported.
 
 - checkInstanceConfiguration      Validates an instance for usage in Group
                                   Replication.
 - configureLocalInstance          Validates and configures an instance for
                                   cluster usage.
 - createCluster                   Creates a MySQL InnoDB cluster.
 - deleteSandboxInstance           Deletes an existing MySQL Server instance on
                                   localhost.
 - deploySandboxInstance           Creates a new MySQL Server instance on
                                   localhost.
 - dropMetadataSchema              Drops the Metadata Schema.
 - getCluster                      Retrieves a cluster from the Metadata Store.
 - help                            Provides help about this class and it's
                                   members
 - killSandboxInstance             Kills a running MySQL Server instance on
                                   localhost.
 - rebootClusterFromCompleteOutage Brings a cluster back ONLINE when all
                                   members are OFFLINE.
 - resetSession                    Sets the session object to be used on the
                                   Dba operations.
 - startSandboxInstance            Starts an existing MySQL Server instance on
                                   localhost.
 - stopSandboxInstance             Stops a running MySQL Server instance on
                                   localhost.
 
For more help on a specific function use: dba.help('<functionName>')
 
e.g. dba.help('deploySandboxInstance')
 
比如獲取當前叢集名稱
mysql-js> dba.getCluster();
<Cluster:myCluster>

4) 日常使用的幾個重要命令 (mysqlsh的JS語法)

dba.checkInstanceConfiguration("root@hostname:3306")     #檢查節點配置例項,用於加入cluster之前

dba.rebootClusterFromCompleteOutage('myCluster');        #重啟 

dba.dropMetadataSchema();                                #刪除schema

var cluster = dba.getCluster('myCluster')                #獲取當前叢集

cluster.checkInstanceState("root@hostname:3306")         #檢查cluster裡節點狀態

cluster.rejoinInstance("root@hostname:3306")             #重新加入節點,我本地測試的時候發現rejoin一直無效,每次是delete後

addcluster.dissolve({force:true})                       #刪除叢集

cluster.addInstance("root@hostname:3306")                #增加節點

cluster.removeInstance("root@hostname:3306")             #刪除節點

cluster.removeInstance('root@host:3306',{force:true})    #強制刪除節點

cluster.dissolve({force:true})                           #解散叢集

cluster.describe();                                      #叢集描述

叢集節點狀態
- ONLINE:  The instance is online and participating in the cluster.
- OFFLINE:  The instance has lost connection to the other instances.
- RECOVERING:  The instance is attempting to synchronize with the cluster by retrieving transactions it needs before it can become an ONLINE member.
- UNREACHABLE:  The instance has lost communication with the cluster.
- ERROR:  The instance has encountered an error during the recovery phase or while applying a transaction

                                                                              InnoDB  Cluster叢集部署中的注意事項                                                                                 

1) 請保證所有的叢集機器在一個子網內,網路必須要通, 不然會失敗;考慮到可以用橋接的方式實現不同網路之間叢集的搭建, 這個並沒有親測;

2) 統一使用hostname進行配置;請更改每臺機器的hosts檔案;

3) 報錯

ERROR:
Group Replication join failed.
ERROR: Error joining instance to cluster: 'host-192-168-1-101:3306' - Query failed. MySQL Error (3092): The server is not configureroperly to be an active member of the group. Please see more details on error log.. Query: START group_replication

通過如下方式進行處理
mysql> install plugin group_replication soname 'group_replication.so'; ##安裝外掛
mysql> set global group_replication_allow_local_disjoint_gtids_join=ON;
mysql> START GROUP_REPLICATION;
mysql> select * from performance_schema.replication_group_members;

4) 報錯

Dba.getCluster: This function is not available through a session to a standalone instance (RuntimeError)
說明叢集中的主節點已經不在該機器上,查詢後更改機器重試一下即可;

5) 報錯

Dba.getCluster: Dba.getCluster: Unable to get cluster. The instance 'host-192-168-1-101:3306' 
may belong to a different ReplicaSet as the one registered in the Metadata since the value of 'group_replication_group_name' 
does not match the one registered in the ReplicaSet's Metadata: possible split-brain scenario. Please connect to another member of the ReplicaSet to get the Cluster. (RuntimeError)

最致命的錯誤,master/slave的資料不一致所致,沒辦法,只能重新來
mysql-js>dba.dropMetadataSchema();

6) 請保證叢集中的資料庫表都存在主鍵,不然會掛掉;

7) 安裝叢集監控,保證叢集中機器掛掉的時候及時啟動,不然所有節點當機的時候就是災難到來之時!!! 到時哭都來不及;

8) 如何重置Innodb cluster叢集環境

主節點:
mysql-js>dba.dropMetadataSchema();   登入mysql-shell清空叢集

mysql> stop group_replication;
mysql> reset master;               (清空日誌,確保和從庫的表沒有衝突奧,)
mysql> reset slave;
 
其他節點(主要清理和主庫的主從資訊, 確保主庫和從庫的表沒有衝突奧)
mysql> stop group_replication;
mysql> reset master;
mysql> reset slave

9) 主機名和 /etc/hosts中名字不一致

出現報錯:
[Repl] Slave I/O for channel 'group_replication_recovery': error connecting to master 'mysql_innodb_cluster_r0430970923@mysql3:3306' - retry-time: 60 retries: 1, Error_code: MY-002005
[ERROR] [MY-011582] [Repl] Plugin group_replication reported: 'There was an error when connecting to the donor server. Please check that group_replication_recovery channel credentials and all MEMBER_HOST column values of performance_schema.replication_group_members table are correct and DNS resolvable.'
[ERROR] [MY-011583] [Repl] Plugin group_replication reported: 'For details please check performance_schema.replication_connection_status table and error log messages of Slave I/O for channel group_replication_recovery.'

10) 主庫的日誌應用卡在某個位置無法應用到從庫

出現報錯:
[ERROR] [MY-010586] [Repl] Error running query, slave SQL thread aborted. Fix the problem, and restart the slave SQL thread with "SLAVE START". We stopped at log 'binlog.000007' position 151
[ERROR] [MY-010584] [Repl] Slave SQL for channel 'group_replication_applier': Error executing row event: 'Unknown database 'mysql_innodb_cluster_metadata'', Error_code: MY-001049
 
重建master:
mysql> stop group_replication;
mysql> reset master; 

11) 報錯

[ERROR] Slave SQL for channel 'group_replication_recovery': Could not execute Write_rows event on table mysql_innodb_cluster_metadata.instances;
Cannot add or update a child row: a foreign key constraint fails (mysql_innodb_cluster_metadata.instances, CONSTRAINT instances_ibfk_1 FOREIGN KEY (host_id) REFERENCES hosts (host_id)),
Error_code: 1452; handler error HA_ERR_NO_REFERENCED_ROW; the event's master log binlog.000001, end_log_pos 3059, Error_code: 1452
 
解決方式:清空表mysql_innodb_cluster_metadata.hosts; 重新建立叢集

12) 報錯

This member has more executed transactions than those present in the group

解決方式:
mysql> stop group_replication;
mysql> reset master;

13) 使用者作業系統資源的限制

[Warning] Buffered warning: Changed limits: max_open_files: 1024 (requested 5000)
[Warning] Buffered warning: Changed limits: table_open_cache: 431 (requested 2000)
 
解決方式:
# vim /etc/security/limits.conf      #  新增下面內容
mysql soft nproc 2047
mysql hard nproc 16384
mysql soft nofile 1024
mysql hard nofile 65535

14) 報錯

dba.rebootClusterFromCompleteOutage: The active session instance isn't the most updated in comparison with the ONLINE instances of the
Cluster's metadata.
 
在叢集沒有起來時某些機器的資料表發生變動,導致資料不一致;
解決方式:
所有MySQL機器通過reset master命令清空binlogs
mysql> reset master;
mysql> show master logs;
然後再執行Dba.rebootClusterFromCompleteOutage重啟叢集。

15) service mysql restart  無法重啟mysql,mysql stuck,並一直輸出日誌'[Note] Plugin group_replication reported: '[GCS] cli_err 2''

解決方式:唯一停止MySQL的命令為:
#pkill -9 mysqld

16) 如何將Multi-Primary改為Single-Primary?

a) 解散原來的叢集:mysql-js> cluster.dissolve({force: true})
b) 每臺主機MySQL修改如下配置:
mysql> set global group_replication_enforce_update_everywhere_checks=OFF;
mysql> set global group_replication_single_primary_mode=ON;
c) 重新建立叢集:
mysql-js> var cluster = dba.createCluster('mysqlCluster');
mysql-js> cluster.addInstance('chianyu@svr2:3306');
mysql-js> cluster.addInstance('chianyu@svr3:3306');

17) 組複製的限制
- 事物鎖缺失問題:
- 組複製建議,事物隔離級別,read commit
- 序列化隔離級別:多主模式不支援
- 併發DDL和DML: 多主模式下,不支援 一邊對一個表進行DDL,另一邊進行更新,這樣對於DDL在其他例項上操作有未檢出的風險
- 外來鍵級聯約束:多主模式下,多級外來鍵依賴對引起多級操作, 因此可能導致未知衝突,建議開啟 group_replication_enforce_update_everywhere_checks=ON
- 大事物,超過5秒未提交,會導致組通訊失敗,
- 多主模式下:select * for update 會導致 死鎖。因為這個鎖並非全組共享。
- 部分複製不支援:組複製下,設定部分複製,會過濾事物,導致組事物不一致。
- Mysql 8.0.11 group_replication_enforce_update_everywhere_checks=ON 多主模式下不支援。
- 停止複製的情況下,某個節點執行命令後再啟動,會因為本地有私有事物,無法加入叢集。需要全域性 reset master 重新開始叢集複製。

18) 多例項環境不要用 3306埠

多例項環境下,某個例項採用了預設的3306埠,會導致經常性的誤操作。
一臺主機最多部署10個例項
 
比如:
cluster節點A伺服器啟用三個埠例項: 3310, 3320, 3330,
cluster節點B伺服器啟用三個埠例項: 3310, 3320, 3330
cluster節點C伺服器啟用三個埠例項: 3310, 3320, 3330
例項資料目錄分別為: /data/mysql3310,  /data/mysql3320, /data/mysql3330
 
管理節點D服務啟動三個埠route埠例項: 3310, 3320, 3330
管理節點E服務啟動三個埠route埠例項: 3310, 3320, 3330
例項資料目錄分別為: /data/router3310, /data/router3320, /data/router3330

相關文章