1、相關概念介紹:html
一、MGR簡介:前端
MySQL Group Replication(簡稱MGR)是MySQL官方推出的一種基於paxos協議的狀態機複製,實現了分佈式下數據的最終一致性。MySQL組複製提供了高可用、高擴展、高可靠的MySQL集羣解決方案。相關網址https://dev.mysql.com/doc/refman/5.7/en/group-replication.html。node
二、MGR特性:mysql
(1)高一致性:基於原生複製及paxos協議的組複製技術,並以插件的方式提供,保證數據一致性git
(2)高容錯性:只要不是大多數節點宕機就能夠繼續工做,有自動檢測機制,當不一樣節點產生資源爭用衝突時,不會出現錯誤,按照先到者優先原則進行處理,而且內置自動化腦裂防禦機制github
(3)高擴展性:節點的新增和移除都是自動的,新節點加入後,會自動從其它節點同步狀態,直到新節點和其它節點保持一致,若是某節點被移除了,其它節點自動更新組信息web
(4)高靈活性:有單主模式和多主模式,單主模式下會自動選擇主節點,全部更新操做都在主節點上進行;多主模式下全部server均可以同時處理更新操正則表達式
三、MGR侷限性:算法
(1)僅支持InnoDB表,而且每張表必定要有一個主鍵,用於write set的衝突檢測sql
(2)必須啓用GTID特性,二進制日誌格式必須設置爲ROW,用於選主與write set
(3)COMMIT可能會致使失敗,相似於快照事務隔離級別的失敗場景
(4)目前一個MGR集羣最多支持9個節點
(5)不支持外鍵於save point特性,沒法作全局間的約束檢測與部分回滾
(6)二進制日誌不支持binlog event checksum
四、MGR集羣架構:
五、MGR與其它複製方式的對比:
(1)MySQL異步複製:
master節點事務的提交不須要通過slave節點的確認,slave節點是否接收到master節點的binlog,master節點並不關心。slave節點接收到master節點的binlog後先寫relay log,最後異步地去執行relay log中的sql應用到本地。因爲master節點的提交不須要確保slave節點的relay log是否被正確接收,當slave節點接收master節點的binlog失敗或relay log應用失敗,master節點沒法感知。假設master節點發生宕機且binlog還未被slave節點接收,而切換程序將slave節點提高爲新的master節點,就會出現數據不一致的狀況。另外,在高併發的狀況下,傳統的主從複製,slave節點可能會與master節點產生較大的延遲。
(2)MySQL半同步複製:
基於傳統異步複製存在的缺陷,MySQL在5.5版本中推出半同步複製,能夠說半同步複製是傳統異步複製的改進,在master節點事務commit以前,必須確保一個slave節點收到relay log且響應給master節點之後,才能進行事務的commit,可是slave節點對於relay log的應用仍然是異步進行的。
(3)MySQL組複製:
基於傳統異步複製和半同步複製的缺陷,即數據的一致性問題沒法保證,MySQL官方在5.7.17版本中正式推出組複製(MySQL Group Replication,簡稱MGR)。由若干個節點共同組成一個複製組,一個事務的提交,必須通過組內大多數節點(N/2+1)決議並經過,才能得以提交。由三個節點組成一個複製組,Consensus層爲一致性協議層,在事務提交過程當中,發生組間通信,由兩個節點決議(certify)經過這個事務,事務才能最終得以提交併響應。一個複製組由若干個節點(數據庫實例)組成,組內各個節點維護各自的數據副本,經過一致性協議實現原子消息和全局有序消息,來實現組內實例數據的一致。
六、ProxySQL簡介:
ProxySQL是MySQL的一款中間件產品,是靈活強大的MySQL代理層,能夠實現讀寫分離,可自定義基於用戶、基於schema、基於語句的規則對SQL語句進行路由,支持動態指定某個SQL進行緩存,支持動態加載配置、故障轉移和一些SQL的過濾功能,能夠實現簡單的sharding。
七、ProxySQL的多層配置系統:
ProxySQL有一套很完整的配置系統,方便DBA對線上的操做。整套配置系統分爲三層,頂層爲RUNTIME,中間層爲MEMORY,底層也就是持久層的DISK和CONFIG FILE。配置結構以下圖所示:
(1)RUNTIME:ProxySQL當前生效的生產環境正在使用的配置,包括global_variables、mysql_servers、mysql_users、mysql_query_rules等,沒法直接修改RUNTIME的配置,必需要從下一層「load」進來,也就是說RUNTIME這個頂級層,就是ProxySQL運行過程當中實際採用的那一份配置,這一份配置就是要影響實際生產環境的。
(2)MEMORY:用戶能夠將MySQL客戶端鏈接到此接口(admin接口),並查詢不一樣的表和數據庫是在MySQL命令行修改的main數據庫中的配置,能夠認爲是SQLite數據庫在內存的鏡像,也就是說MEMORY這個中間層,上面鏈接着生產配置項RUNTIME層,下面鏈接着持久化層DISK和CONFIG FILE。MEMORY也是修改ProxySQL的惟一正常入口。修改一個配置通常都是先在MEMORY層完成,確認無誤後再加載到RUNTIME和持久化到磁盤上,也就是說在這層能夠正常操做ProxySQL配置,MEMORY層中的配置修改不會影響生產環境,也不影響磁盤中保存的數據,經過此接口能夠修改main數據庫中以mysql_開頭的表(如:mysql_servers、mysql_users、mysql_query_rules)和global_variables表等。
(3)DISK和CONFIG FILE:持久化配置信息,通常保存在/var/lib/proxysql/proxysql.db數據文件中,重啓後內存中的配置信息會丟失,因此須要將配置信息保留在磁盤中。重啓時,能夠從磁盤快速加載回來。配置文件/etc/proxysql.cnf只在第一次初始化時用到。DISK和CONFIG FILE這一層是持久化層,作的任何配置更改,若是不持久化,重啓後,配置將丟失。
八、ProxySQL相關網址:
(1)GitHub官網:https://github.com/sysown/proxysql/releases
(2)Percona官網:https://www.percona.com/downloads/proxysql/
2、準備工做(四個節點都須要執行以下操做):
一、 演示環境:
IP |
操做系統 |
主機名 |
角色 |
軟件包版本 |
安裝方式 |
192.168.1.143 |
CentOS 7.6 x86_64 |
node1 |
proxysql |
2.0.4-percona-1.2 |
yum |
192.168.1.144 |
CentOS 7.6 x86_64 |
node2 |
master |
5.7.26-log MySQL Community Server |
rpm |
192.168.1.145 |
CentOS 7.6 x86_64 |
node3 |
slave1 |
5.7.26-log MySQL Community Server |
rpm |
192.168.1.146 |
CentOS 7.6 x86_64 |
node4 |
slave2 |
5.7.26-log MySQL Community Server |
rpm |
二、實驗架構:
三、關閉SELinux和firewalld
四、配置epel源
五、配置節點時間同步
六、配置主機名
七、配置/etc/hosts文件:
# vim /etc/hosts
192.168.1.143 node1
192.168.1.144 node2
192.168.1.145 node3
192.168.1.146 node4
八、下載MySQL 5.7軟件包,https://dev.mysql.com/downloads/mysql/5.7.html#downloads
3、構建MGR單主高可用集羣(如未特殊說明,在master、slave1和slave2節點中分別執行以下操做):
一、安裝配置MySQL:
(1)卸載CentOS 7.6自帶的MariaDB:
# rpm -qa | grep -i mariadb --> mariadb-libs-5.5.60-1.el7_5.x86_64
# rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64
(2)若是以前安裝過MySQL,先卸載:# rpm -qa | grep -i mysql
(3)若是存在/etc/my.cnf配置文件,先刪除:# rm -rf /etc/my.cnf
(4)將軟件包上傳至主機/tmp目錄下:
mysql-community-client-5.7.26-1.el7.x86_64.rpm
mysql-community-libs-5.7.26-1.el7.x86_64.rpm
mysql-community-common-5.7.26-1.el7.x86_64.rpm
mysql-community-libs-compat-5.7.26-1.el7.x86_64.rpm
mysql-community-devel-5.7.26-1.el7.x86_64.rpm
mysql-community-server-5.7.26-1.el7.x86_64.rpm
(5)安裝MySQL軟件包:# yum -y localinstall *.rpm
(6)初始化MySQL數據:# mysqld --initialize --user=mysql --datadir=/var/lib/mysql
備註:初始化以前確保/var/lib/mysql目錄爲空
(7)修改MySQL配置文件:
# mv /etc/my.cnf /etc/my.cnf.bak
# vim /etc/my.cnf
master節點:
[mysqld]
port=3306
socket=/var/lib/mysql/mysql.sock
datadir=/var/lib/mysql
pid-file=/var/run/mysqld/mysqld.pid
log-error=/var/log/mysqld.log
lower_case_table_names=1
character_set_server=utf8mb4
collation_server=utf8mb4_general_ci
innodb_file_per_table=1
skip_name_resolve=1
slow_query_log=1
slow_query_log_file=mysql-slow.log
symbolic-links=0
explicit_defaults_for_timestamp=1
log_bin=mysql-bin
log_bin_index=mysql-bin.index
binlog_format=row
server_id=1
gtid_mode=on
enforce_gtid_consistency=on
master_info_repository=table
relay_log_info_repository=table
binlog_checksum=none
log_slave_updates=on
備註:
a、slave1節點中server_id=2,增長read_only=1,其它參數保持不變
b、slave2節點中server_id=3,增長read_only=1,其它參數保持不變
(8)啓動MySQL服務:
# systemctl start mysqld.service
# ss -tunlp | grep mysqld
# systemctl enable mysqld.service
# systemctl status mysqld.service
(9)查看root@localhost用戶的初始密碼:# grep password /var/log/mysqld.log
(10)配置MySQL安全向導:# mysql_secure_installation
二、安裝group_replication插件:
# mysql -uroot -p
mysql> install plugin group_replication soname 'group_replication.so';
mysql> show plugins;
備註:插件位於/usr/lib64/mysql/plugin/group_replication.so
三、修改MySQL配置文件,增長MGR相關配置:
# vim /etc/my.cnf
master節點:
[mysqld]
transaction_write_set_extraction=XXHASH64
group_replication_group_name='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'
group_replication_start_on_boot=off
group_replication_local_address='192.168.1.144:24901'
group_replication_group_seeds='192.168.1.144:24901,192.168.1.145:24901,192.168.1.146:24901'
group_replication_bootstrap_group=off
group_replication_enforce_update_everywhere_checks=off
group_replication_single_primary_mode=on
# systemctl restart mysqld.service
備註1:
(1)slave1節點中group_replication_local_address='192.168.1.145:24901',其它參數保持不變
(2)slave2節點中group_replication_local_address='192.168.1.146:24901',其它參數保持不變
備註2:參數說明
(1)gtid_mode=on:啓用GTID模式
(2)enforce_gtid_consistency=on:啓用強制GTID一致性
(3)master_info_repository=table:將master.info元數據保存在系統表中
(4)relay_log_info_repository=table:將relay.info元數據保存在系統表中
(5)binlog_checksum=none:禁用二進制日誌事件校驗
(6)log_slave_updates=on:啓用級聯複製
(7)transaction_write_set_extraction=XXHASH64:使用XXHASH64哈希算法將其編碼爲散列
(8)group_replication_group_name='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa':加入或建立的組名稱,值必須是有效的UUID
(9)group_replication_start_on_boot=off:server啓動時不自動啓動組複製
(10)group_replication_local_address='192.168.1.144:24901':該節點的MGR模塊通訊地址,自定義端口24901用於與組中的其它成員進行內部通訊
(11)group_replication_group_seeds='192.168.1.144:24901,192.168.1.145:24901,192.168.1.146:24901':組成員的IP和端口
(12)group_replication_bootstrap_group=off:不執行MGR複製組的初始化操做,若是該參數設置爲on,表示會建立一個MGR複製組,在此處master是第一個初始化節點,動態開啓該參數,而後再啓動MGR
(13)group_replication_enforce_update_everywhere_checks=off:該參數設置爲off,表示啓用單主模式,設置爲on,表示啓用多主模式
(14)group_replication_single_primary_mode=on:該參數設置爲on,表示啓用單主模式,設置爲off,表示啓用多主模式
四、建立具備複製權限的用戶repluser:
mysql> set sql_log_bin=0;
mysql> create user 'repluser'@'192.168.1.%' identified by '123456';
mysql> grant replication slave on *.* to 'repluser'@'192.168.1.%';
mysql> flush privileges;
mysql> set sql_log_bin=1;
備註:組複製使用異步複製協議來實現分佈式恢復,在將組成員加入組以前將其同步,該用戶爲故障恢復的異步複製通道group_replication_recovery所用,複製通道用於在組成員之間傳輸事務
五、構建MGR集羣:
mysql> change master to master_user='repluser',master_password='123456' for channel 'group_replication_recovery';
六、啓動MGR集羣:
master節點執行以下操做:
mysql> set global group_replication_bootstrap_group=on;
mysql> start group_replication;
mysql> set global group_replication_bootstrap_group=off;
slave1和slave2節點分別執行以下操做,加入複製組:
mysql> set global group_replication_allow_local_disjoint_gtids_join=on;
mysql> start group_replication;
備註:
(1)set global group_replication_bootstrap_group=on:只需在master節點中執行,表示之後加入集羣的成員以master節點爲準,且只需執行一次
(2)set global group_replication_bootstrap_group=off:確保master節點下一次啓動時不會再進行初始化,致使複製組出現分裂
七、查看MGR狀態信息:
mysql> select * from performance_schema.replication_group_members;
備註:按照MEMBER_ID進行升序排序,每一個節點執行結果相同
mysql> select * from performance_schema.replication_connection_status\G
master節點:
slave1節點:
slave2節點:
mysql> show global variables like '%group_replication%';
mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;
master節點:
備註:is_primary_mode的值爲1說明此節點爲master節點
slave1節點:
slave2節點:
八、master節點建立測試數據:
mysql> create database db;
mysql> use db;
mysql> create table tb(id int unsigned auto_increment primary key not null,age int not null);
mysql> desc tb;
mysql> insert into tb(age) values(35),(40);
mysql> select * from tb;
九、slave1和slave2節點分別查看測試數據:
mysql> show databases like 'db';
mysql> select * from db.tb;
4、安裝配置ProxySQL(如未特殊說明,在proxysql節點中執行以下操做):
一、配置percona源:
# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm
# yum repolist
二、安裝MySQL客戶端工具:# yum -y install Percona-Server-client-57
三、安裝ProxySQL:# yum list | grep -i percona # yum -y install proxysql2 # proxysql --version
備註:ProxySQL相關文件
(1)配置文件:/etc/proxysql-admin.cnf、/etc/proxysql.cnf
(2)SQLite數據文件:/var/lib/proxysql/proxysql.db
(3)日誌文件:/var/lib/proxysql/proxysql.log
備註:若是存在proxysql.db數據文件,則ProxySQL啓動過程當中將不會讀取proxysql.cnf配置文件的內容來初始化ProxySQL
四、啓動ProxySQL:
# systemctl start proxysql.service
# ss -tunlp | grep proxysql
備註:6032是ProxySQL的管理端口號,6033是對外服務的端口號
五、使用默認的admin用戶(密碼也爲admin)登陸ProxySQL管理界面:
# mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> '
備註:若是須要建立一個新用戶marion,密碼爲123456,則可執行以下操做
proxysql> update global_variables set variable_value='admin:admin;marion:123456' where variable_name='admin-admin_credentials';
proxysql> load admin variables to runtime;
proxysql> save admin variables to disk;
備註:不管執行任何操做,都須要執行load *** to runtime(從memory加載到runtime)、save *** to disk(持久化到磁盤)
六、master節點建立ProxySQL的監控用戶monitor和對外訪問用戶proxysql,並賦予權限:
mysql> create user 'monitor'@'192.168.1.%' identified by '123456';
mysql> grant all on *.* to 'monitor'@'192.168.1.%';
mysql> create user 'proxysql'@'192.168.1.%' identified by '123456';
mysql> grant all on *.* to 'proxysql'@'192.168.1.%';
mysql> flush privileges;
七、添加主從服務器列表:
proxysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(10,'192.168.1.144',3306,1,'master'),(10,'192.168.1.145',3306,1,'slave1'),(10,'192.168.1.146',3306,3,'slave2');
proxysql> load mysql servers to runtime;
proxysql> save mysql servers to disk;
proxysql> select * from mysql_servers;
備註:
(1)表mysql_servers:後端能夠鏈接MySQL主機的列表
(2)全部節點都是ONLINE狀態
(3)slave2節點的查詢權重調整爲3,爲了讓更多的讀請求路由到這臺配置更好的主機上
(4)表mysql_servers經常使用字段說明:
字段 |
說明 |
hostgroup_id |
ProxySQL經過hostgroup的形式組織後端db實例,一個hostgroup表明同屬於一個角色,默認爲0 |
hostname |
後端實例IP |
port |
後端實例監聽端口,默認爲3306 |
status |
後端實例狀態,默認爲online,可取值爲: Ø online:當先後端實例狀態正常 Ø shunned:臨時被剔除,可能由於後端too many connections error,或者超過了可容忍延遲閥值max_replication_lag Ø offline_soft:「軟離線」狀態,再也不接收新的鏈接,但已創建的鏈接會等待活躍事務完成 Ø offline_hard:「硬離線」狀態,再也不接收新的鏈接,已創建的鏈接或被強制中斷,當後端實例宕機或網絡不可達時,會出現 |
weight |
後端實例權重,默認爲1 |
max_connections |
容許鏈接到該後端實例的最大鏈接數,不能大於MySQL設置的max_connections,若是後端實例hostname:port在多個hostgroup中,以較大者爲準,而不是各自獨立容許的最大鏈接數,默認爲1000 |
max_replication_lag |
容許的最大延遲,master節點不受此影響,默認爲0,若是>0,monitor模塊監控主從延遲大於閥值時,會臨時把它變爲shunned |
max_latency_ms |
mysql_ping響應時長,大於這個閥值會把它從鏈接池中剔除(即便是ONLINE狀態),默認爲0 |
comment |
備註 |
(5)查看錶中的字段可以使用命令proxysql> show create table mysql_servers\G
(6)查看錶中的數據可以使用命令proxysql> select * from mysql_servers\G
八、配置和註冊監控用戶monitor,並驗證監控信息:
proxysql> set mysql-monitor_username='monitor';
proxysql> set mysql-monitor_password='123456';
proxysql> load mysql variables to runtime;
proxysql> save mysql variables to disk;
proxysql> select * from global_variables where variable_name in ('mysql-monitor_username','mysql-monitor_password');
proxysql> select * from monitor.mysql_server_connect_log order by time_start_us desc limit 6;
proxysql> select * from monitor.mysql_server_ping_log order by time_start_us desc limit 6;
九、配置ProxySQL主從分組信息:
proxysql> insert into mysql_replication_hostgroups values (10,20,'read_only','proxysql');
proxysql> load mysql servers to runtime;
proxysql> save mysql servers to disk;
備註:
(1)表mysql_replication_hostgroups經常使用字段說明:
字段 |
說明 |
writer_hostgroup |
寫入組的編號,此處爲10 |
reader_hostgroup |
讀取組的編號,此處爲20 |
check_type |
可取值爲:'read_only'、'innodb_read_only'、'super_read_only',默認值爲'read_only' |
comment |
備註 |
(2)查看錶中的字段可以使用命令proxysql> show create table mysql_replication_hostgroups\G
(3)查看錶中的數據可以使用命令proxysql> select * from mysql_replication_hostgroups\G
proxysql> select * from mysql_replication_hostgroups;
proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;
備註:ProxySQL會根據MySQL中read_only的取值將主機進行分組,read_only=0的master節點被分配到編號爲10的寫入組,而read_only=1的兩個slave節點則被分配到編號爲20的讀取組
十、配置對外訪問用戶proxysql:
proxysql> insert into mysql_users(username,password,default_hostgroup) values('proxysql','123456',10);
proxysql> load mysql users to runtime;
proxysql> save mysql users to disk;
proxysql> select * from mysql_users\G
備註:
(1)表mysql_users:配置後端數據庫用戶和監控用戶
(2)表mysql_users經常使用字段說明:
字段 |
說明 |
username |
前端鏈接ProxySQL,及ProxySQL將SQL語句路由給後端MySQL實例中所使用的用戶名 |
password |
後端MySQL實例中用戶名對應的密碼,能夠是明文密碼,也能夠是hash加密後的密文,若是想使用hash密碼,能夠先在某個MySQL節點中執行select password(PASSWORD),而後將加密結果複製到該字段 |
active |
只有active=1的用戶纔是有效的用戶 |
default_hostgroup |
該用戶名默認的路由目標,如:指定root用戶的該字段值爲10時,則使用root用戶發送的SQL語句默認狀況下將路由到hostgroup_id=10組中的某個節點,若是該用戶的請求沒有匹配到規則時,默認發送到這個hostgroup |
default_schema |
用戶默認登陸後端MySQL實例時鏈接的數據庫,若是爲NULL,則由全局變量mysql-default_schema決定,默認爲information_schema |
transaction_persistent |
默認爲1,表示啓用事務持久化,鏈接上ProxySQL的會話後,若是在一個hostgroup中開啓了事務,那麼在事務提交/回滾以前,全部的語句都路由到同一個組中,不管是否會匹配上其它路由規則,直到事務結束,避免語句分散到不一樣組(更進一步的,它會自動禁用multiplexing,讓同一個事務的語句從同一個鏈接路由出去,保證路由到同一個組的同一個節點),避免發生髒讀、幻讀等狀況 |
(3)查看錶中的字段可以使用命令proxysql> show create table mysql_users\G
(4)查看錶中的數據可以使用命令proxysql> select * from mysql_users\G
十一、驗證經過對外服務6033端口登陸的是master節點:
# mysql -uproxysql -p -h192.168.1.143 -P6033 -e 'select @@hostname;'
備註:node2爲master節點的主機名
十二、配置路由規則,實現讀寫分離:
proxysql> insert into mysql_query_rules(active,match_pattern,destination_hostgroup,apply) values(1,'^select.*for update$',10,1),(1,'^select',20,1);
proxysql> load mysql query rules to runtime;
proxysql> save mysql query rules to disk;
proxysql> select rule_id,active,match_pattern,destination_hostgroup,apply from mysql_query_rules;
備註:
(1)select for update會產生一個寫鎖,對數據查詢的時效性要求較高,因此將它分配到編號爲10的寫入組
(2)除了select for update之外全部select開頭的語句所有分配到編號爲20的讀取組
(3)其它全部操做都默認路由到寫入組(mysql_users表中字段default_hostgroup定義的值)
(4)表mysql_query_rules:指定query路由到後端不一樣主機的規則列表
(5)表mysql_query_rules經常使用字段說明:
字段 |
說明 |
rule_id |
表主鍵,自增,規則處理是以rule_id的順序進行 |
active |
默認爲0,值爲1時表示啓用此路由規則 |
username |
若是不爲空,該規則只匹配該用戶 |
schemaname |
若是不爲空,該規則只匹配該數據庫名稱,若是爲NULL,不表明鏈接沒有使用schema,而是不管任何schema都進一步匹配 |
client_addr |
匹配客戶端來源IP |
proxy_addr |
匹配本地ProxySQL的IP |
proxy_port |
匹配本地ProxySQL的端口 |
match_digest |
描述規則的正則表達式,1.4版本之後,正則表達式支持pcre和pcre2兩種,默認使用pcre,即perl語言支持的正則表達式,query digest是指對查詢去掉具體值後進行「模糊化」後的查詢 |
match_pattern |
正則表達式匹配查詢 |
negate_match_pattern |
反向匹配,至關於對match_digest/match_pattern的匹配取反,默認爲0 |
re_modifiers |
修改正則匹配的參數,如默認的:忽略大小寫CASELESS、禁用GLOBAL,默認爲CASELESS |
destination_hostgroup |
該路由規則發往哪一個組 |
cache_ttl |
用戶查詢緩存的時間閾值,單位爲毫秒 |
timeout |
這一類查詢執行的最大時間(單位爲毫秒),超時則自動kill,這是對後端db的保護機制,默認mysql-default_query_timeout的值是10h |
retries |
語句在執行失敗時,重試的次數,默認由mysql-query_retries_on_failure變量指定,默認爲1 |
delay |
查詢延遲執行,這是ProxySQL提供的限流機制,會讓其它的查詢優先執行 |
apply |
默認爲0,值爲1時表示該正則匹配後,將再也不接受其它匹配,直接轉發 |
comment |
備註 |
(6)查看錶中的字段可以使用命令proxysql> show create table mysql_query_rules\G
(7)查看錶中的數據可以使用命令proxysql> select * from mysql_query_rules\G
1三、ProxySQL中的內置數據庫及經常使用表、字段說明:
proxysql> show databases;
備註:默認已處於main數據庫中
(1)main:內存配置數據庫,即memory,表中存放後端db實例、用戶驗證、路由規則等信息
查看main數據庫中的表:proxysql> show tables from main;
備註:表名以runtime_開頭的表示ProxySQL當前正在運行的配置內容,不能經過DML語句修改,但能從其它層級加載,只能修改對應的不以runtime_開頭的表,而後load *** to runtime(從memory加載到runtime)、save *** to disk(持久化到磁盤)
(2)disk:持久化到磁盤的配置,SQLite數據文件
查看disk數據庫中的表:proxysql> show tables from disk;
(3)stats:ProxySQL將收集的統計數據存儲在stats數據庫中,包括到後端各命令的執行次數、流量、processlist、查詢種類彙總/執行時間等等
查看stats數據庫中的表:proxysql> show tables from stats;
a、表stats_mysql_commands_counters:統計各類SQL類型的執行次數和時間
表stats_mysql_commands_counters經常使用字段說明:
字段 |
說明 |
Command |
已執行的SQL命令的類型,如:FLUSH、INSERT、KILL、SELECT等 |
Total_Time_us |
執行該類型命令的總時間(以微秒爲單位) |
Total_cnt |
執行該類型命令的總數 |
cnt_100us、cnt_500us、cnt_1ms、cnt_5ms、cnt_10ms、cnt_50ms、cnt_100ms、cnt_500ms、cnt_1s、cnt_5s、cnt_10s、cnt_INFs |
在指定的時間內執行該類型的命令總數和前一個命令的總數 |
b、表stats_mysql_connection_pool:鏈接後端MySQL的鏈接池信息
表stats_mysql_connection_pool經常使用字段說明:
字段 |
說明 |
hostgroup |
後端主機所屬的主機組,單個後端主機能夠屬於多個主機組 |
srv_host |
後端主機正在偵聽鏈接的IP |
srv_port |
後端主機正在偵聽鏈接的TCP Port |
status |
後端實例狀態,默認爲online,可取值爲: Ø online:當先後端實例狀態正常 Ø shunned:臨時被剔除,可能由於後端too many connections error,或者超過了可容忍延遲閥值max_replication_lag Ø offline_soft:「軟離線」狀態,再也不接收新的鏈接,但已創建的鏈接會等待活躍事務完成 Ø offline_hard:「硬離線」狀態,再也不接收新的鏈接,已創建的鏈接或被強制中斷,當後端實例宕機或網絡不可達時,會出現 |
ConnUsed |
ProxySQL當前使用多少個鏈接來向後端主機發送查詢 |
ConnFree |
目前有多少個空閒鏈接 |
ConnOK |
成功創建了多少個鏈接 |
ConnERR |
沒有成功創建多少個鏈接 |
Queries |
路由到此特定後端主機的查詢數 |
Bytes_data_sent |
發送到後端主機的數據量 |
Bytes_data_recv |
從後端主機接收的數據量 |
Latency_us |
從monitor報告的當前ping(以毫秒爲單位)的延遲時間 |
c、表stats_mysql_global:與MySQL相關的代理級別的全局統計
表stats_mysql_global經常使用字段說明:
字段 |
說明 |
Client_Connections_aborted |
因爲無效憑據或max_connections而致使的前端鏈接數已達到 |
Client_Connections_connected |
當前鏈接的前端鏈接數 |
Client_Connections_created |
到目前爲止建立的前端鏈接數 |
Questions |
從前端發送的查詢總數 |
Slow_queries |
在全局變量中定義的運行時間超過閾值的毫秒數的查詢數mysql-long_query_time |
d、表stats_mysql_processlist:相似MySQL的show processlist的命令,查看各線程的狀態
表stats_mysql_processlist經常使用字段說明:
字段 |
說明 |
ThreadID |
ProxySQL線程ID |
SessionID |
ProxySQL會話ID,經過此ID能夠進行kill操做 |
user |
經過MySQL客戶端鏈接ProxySQL的用戶 |
db |
當前選擇的數據庫 |
cli_host |
鏈接ProxySQL的MySQL客戶端IP |
cli_port |
鏈接ProxySQL的TCP端口 |
hostgroup |
當前主機組,若是正在處理查詢,則是查詢已被路由或將要路由的主機組,或默認主機組,能夠查看該SQL究竟是路由到哪一個主機組中 |
l_srv_host |
ProxySQL的IP |
l_srv_port |
ProxySQL的TCP端口 |
srv_host |
後端MySQL服務器的IP |
srv_port |
後端MySQL服務器的TCP端口 |
command |
正在執行的MySQL查詢類型 |
time_ms |
命令執行的時長(以毫秒爲單位) |
info |
正在執行的SQL |
e、表stats_mysql_query_rules:統計路由命中次數
表stats_mysql_query_rules經常使用字段說明:
字段 |
說明 |
rule_id |
路由規則的id與main.mysql_query_rules的id對應 |
hits |
此路由規則的匹配總數,若是當前傳入的查詢符合規則,則會記錄一次命中 |
(4)monitor:存儲monitor模塊收集的信息,主要是對後端db的健康/延遲檢查
查看monitor數據庫中的表:proxysql> show tables from monitor;
表名 |
說明 |
mysql_server_connect_log |
鏈接全部MySQL主機以檢查它們是否可用,該表用來存放檢測鏈接的日誌,由變量mysql-monitor_connect_interval來控制其檢測的時間間隔,由參數mysql-monitor_connect_timeout控制鏈接是否超時(默認爲200毫秒) |
mysql_server_ping_log |
使用mysql_ping API ping後端MySQL主機檢查它們是否可用,該表用來存放ping的日誌,由變量mysql-monitor_ping_interval控制ping的時間間隔,默認爲10000(單位毫秒,至關於10秒) |
mysql_server_replication_lag_log |
後端MySQL服務主從延遲的檢測,由參數mysql-monitor_replication_lag_interval控制檢測時間間隔,由mysql_servers.max_replication_lag列控制,默認爲10000(單位毫秒,至關於10秒) |
備註:
a、查看錶中的字段可以使用命令proxysql> show create table 表名\G
b、查看錶中的數據可以使用命令proxysql> select * from 表名\G
5、測試ProxySQL:
一、測試讀寫分離:
(1)清空stats_mysql_query_digest表:
# mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> '
proxysql> select * from stats_mysql_query_digest_reset;
proxysql> select * from stats_mysql_query_digest;
# mysql -uproxysql -p -h192.168.1.143 -P6033
mysql> select * from db.tb;
mysql> insert into db.tb(age) values(0),(100);
mysql> select * from db.tb for update;
備註:
a、表stats_mysql_query_digest:SQL的執行次數、時間消耗等
b、表stats_mysql_query_digest經常使用字段說明:
字段 |
說明 |
hostgroup |
發送查詢的主機組,值爲-1表示查詢的是查詢緩存 |
schemaname |
查詢的數據庫 |
username |
鏈接ProxySQL的用戶名 |
digest_text |
參數剝離的實際SQL文本 |
count_star |
執行查詢的總次數 |
first_seen |
unix時間戳,查詢經過代理路由查詢的第一時刻 |
last_seen |
unix時間戳,查詢經過代理路由查詢的最後一刻(到目前爲止) |
sum_time |
執行此類查詢的總時間(以微秒爲單位) |
min_time |
執行此類查詢時指望的持續時間範圍,min_time表示到目前爲止所看到的最小執行時間 |
max_time |
執行此類查詢時指望的持續時間範圍,max_time表示最大執行時間,以微秒爲單位 |
c、查看錶中的字段可以使用命令proxysql> show create table stats.stats_mysql_query_digest\G
d、查看錶中的數據可以使用命令proxysql> select * from stats.stats_mysql_query_digest\G
e、表stats_mysql_query_digest_reset和表stats_mysql_query_digest結構一致
(2)經過查詢stats_mysql_query_digest表來監控查詢狀態:
proxysql> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest;
備註:
a、select * from tb for update語句已經自動路由到編號爲10的寫入組,即master節點
b、select * from tb語句已經自動路由到編號爲20的讀取組,即slave節點
二、測試讀請求負載均衡:
# for i in {1..12}; do mysql -uproxysql -p123456 -h192.168.1.143 -P6033 -e 'select @@hostname' -s -N; done
選項說明:
(1)-s:以製表符做爲分隔符打印結果
(2)-N:結果中不包含列名
備註:上述命令執行結果可得出讀請求在兩臺slave節點間切換,且node3和node4的出現比例接近1:3
三、測試ProxySQL故障轉移:
(1)單主模型腳本gr_sw_mode_checker.sh,https://github.com/ZzzCrazyPig/proxysql_groupreplication_checker
備註:共有三個腳本提供下載
a、proxysql_groupreplication_checker.sh:用於multi-primary模式,能夠實現讀寫分離及故障轉移,同一時間點多個節點均可以寫
b、gr_mw_mode_cheker.sh:用於multi-primary模式,能夠實現讀寫分離及故障轉移,但在同一時間點只能有一個節點能夠寫
c、gr_sw_mode_checker.sh:用於single-primary模式,能夠實現讀寫分離及故障轉移
(2)將下載的腳本gr_sw_mode_checker.sh放置至/var/lib/proxysql目錄中,並賦予執行權限和修改屬主屬組:
# chmod +x /var/lib/proxysql/gr_sw_mode_checker.sh
# chown proxysql.proxysql /var/lib/proxysql/gr_sw_mode_checker.sh
(3)下載addition_to_sys.sql,https://github.com/lefred/mysql_gr_routing_check/
(4)master節點建立表sys.gr_member_routing_candidate_status:# mysql -uroot -p < addition_to_sys.sql
mysql> select * from sys.gr_member_routing_candidate_status;
master節點:
slave1節點:
slave2節點:
(5)配置scheduler:
proxysql> insert into scheduler(active,interval_ms,filename,arg1,arg2,arg3,arg4) values(1,5000,'/var/lib/proxysql/gr_sw_mode_checker.sh',10,20,1,'/var/lib/proxysql/gr_sw_mode_checker.log');
proxysql> load scheduler to runtime;
proxysql> save scheduler to disk;
備註1:
a、表scheduler經常使用字段說明
字段 |
說明 |
active |
值爲1時容許計劃程序按期執行提供的腳本,默認爲1 |
interval_ms |
每隔多少毫秒執行一次腳本,5000毫秒爲5秒 |
filename |
腳本的存放路徑 |
arg1~arg4 |
腳本接收到的輸入參數 |
comment |
備註 |
b、查看錶中的字段可以使用命令proxysql> show create table scheduler\G
c、查看錶中的數據可以使用命令proxysql> select * from scheduler\G
d、問題排查可查看日誌文件/var/lib/proxysql/gr_sw_mode_checker.log
備註2:腳本gr_sw_mode_checker.sh用法
gr_sw_mode_cheker.sh <hostgroup_id write> <hostgroup_id read> [write node can be read : 1(YES: default) or 0(NO)] [log_file]
a、arg1:hostgroup_id write
b、arg2:hostgroup_id read
c、arg3:write node can be read : 1(YES: default) or 0(NO)
d、arg4:log_file, default: './checker.log'
proxysql> select * from scheduler\G
(6)查看MGR狀態信息:
proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;
mysql> select * from performance_schema.replication_group_members;
mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;
master節點:
備註:is_primary_mode的值爲1說明此節點爲master節點
slave1節點:
slave2節點:
(7)master節點模擬MySQL服務故障:# systemctl stop mysqld.service
(8)查看MGR狀態信息:
proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;
mysql> select * from performance_schema.replication_group_members;
mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;
slave1節點:
slave2節點:
備註:當master節點意外宕機或下線,在知足大多數節點存活的狀況下,group內部發起選舉,選出下一個可用的讀節點,提高其爲master節點。master節點選舉根據group內剩餘存活節點的UUID按字典升序排列,而後選擇排在最前的節點做爲新的master節點。is_primary_mode的值爲1說明slave2節點已經被選舉爲新的master節點。
mysql> select * from sys.gr_member_routing_candidate_status;
slave1節點:
slave2節點:
備註:slave2節點中的read_only參數的值已經自動修改成0
(9)slave2節點建立測試數據:
mysql> insert into db.tb(age) values(60),(80);
mysql> select * from db.tb;
(10)slave1節點查看測試數據:
mysql> select * from db.tb;
(11)原master節點恢復MySQL服務:# systemctl start mysqld.service
(12)原master節點加入複製組:mysql> start group_replication;
(13)查看MGR狀態信息:
proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;
mysql> select * from performance_schema.replication_group_members;
mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;
原master節點:
備註:新上線的原master節點現已變爲slave節點
slave1節點:
slave2節點:
mysql> select * from sys.gr_member_routing_candidate_status;
原master節點:
備註:原master節點中的read_only參數的值已經自動修改成1
slave1節點:
slave2節點:
(14)原master節點已經複製了最新的測試數據:
mysql> select * from db.tb;
四、使用sysbench進行壓測:
(1)安裝sysbench:# yum -y install sysbench
(2)將用戶proxysql的transaction_persistent值修改成0:
proxysql> update mysql_users set transaction_persistent=0 where username='proxysql';
proxysql> load mysql users to runtime;
proxysql> save mysql users to disk;
(3)prepare:
# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua prepare
備註:經常使用選項說明
a、--threads:使用的線程數
b、--events:事件總數
c、--time:以秒爲單位的總執行時間
d、--report-interval:以秒爲單位按期報告具備指定間隔的中間統計信息
e、--mysql-host:ProxySQL所在主機的IP
f、--mysql-port:ProxySQL對外服務的端口號
g、--mysql-user:MySQL user
h、--mysql-password:MySQL password
i、--mysql-db:在db數據庫中建立表sbtest1,並插入10000條數據
(4)run:
# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua run
備註:不要Ctrl + c終止壓測
(5)壓測過程當中複製會話,觀察讀寫分離狀態:
proxysql> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest\G
備註:上述命令執行結果可得出寫請求都路由到編號爲10的寫入組,而讀請求都路由到編號爲20的讀取組
五、測試查詢緩存:
ProxySQL的查詢緩存和MySQL的查詢緩存有點相似,但不徹底同樣,ProxySQL的查詢緩存若是在指定時間大小範圍內發送的SQL一摸同樣,那麼直接返回結果集,而返回的結果集可能並非準確的查詢結果,因此須要設置合適的時間範圍,既能提高性能,又得知足業務需求,即查詢結果足夠的「新」。針對一些查詢頻率很高但結果並不須要太精確的業務,能夠單獨給這些SQL配置查詢緩存。
(1)啓用查詢緩存:
proxysql> update mysql_query_rules set cache_ttl=2000 where active=1 and destination_hostgroup=20;
proxysql> load mysql query rules to runtime;
proxysql> save mysql query rules to disk;
(2)壓測:
# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua run
(3)壓測過程當中複製會話,觀察讀寫分離狀態:
proxysql> select hostgroup,digest_text,sum_time from stats_mysql_query_digest\G
備註:能夠看到hostgroup的值部分爲-1,表示這些查詢使用了查詢緩存,且耗時爲0
六、啓用Web統計功能:
(1)查看變量admin-web_enabled是否啓用:
proxysql> select * from global_variables where variable_name like 'admin-web%';
(2)啓用變量admin-web_enabled:
proxysql> set admin-web_enabled='true';
proxysql> load admin variables to runtime;
proxysql> save admin variables to disk;
proxysql> select * from global_variables where variable_name like 'admin-web%';
(3)查看登陸Web界面的用戶名、密碼和端口:
proxysql> select * from global_variables where variable_name like 'admin-web%' or variable_name LIKE 'admin-stats%';
(4)瀏覽器中訪問192.168.1.143:6080,用戶名和密碼均爲stats: