MySQL用中间件ProxySQL实现读写分离和主节点故障应用无感应
昨天做的用proxysql實現的讀寫分離,但是在實際的應用中這樣的結構還很不完整,如果主節點出現故障那么整個拓撲的數據庫也無法通過proxysql來調用了,所以還需要增加主節點故障后proxysql能夠自動切換到新的主節點的功能。
(MGR)組復制能夠完成主節點故障后推選出來新的主節點,不過在應用層不可能通過改新的主節點的IP來連接新的主節點,通過mgr+proxysql可能實際主節點故障時應用無感應自動切換到新的主節點。
描述下上面的實現思路:三個節點使multi-primary的方式連接,應用通過連接ProxySQL中間件,根據sql的屬性(是否為select語句)來決定連接哪一個節點,一個可寫節點,兩個只讀節點(其實三個都是可寫節點,只不過通過proxysql進行了讀寫分離)。如果默認的可寫節點掛掉的話,proxysql通過定期運行的調度器會將另一個只讀節點的其中一臺設為可寫節點,實際主節點故障應用無感應的要求。
上述的整個過程中,應用無需任何變動。應用從意識發生了故障,到連接重新指向新的主,正常提供服務,秒級別的間隔。
下面做一下這個配置:
1.各server說明:
qht131????172.17.61.131????master1
qht132????172.17.61.132????master2
qht133????172.17.61.133????master3
qht134????172.17.61.134????proxysql
multi-primary的主從復制結構 :
mysql>??SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME??????????????| MEMBER_ID????????????????????????????| MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | bb0dea82-58ed-11e8-94e5-000c29e8e89b | qht131??????|????????3306 | ONLINE???????|
| group_replication_applier | bb0dea82-58ed-11e8-94e5-000c29e8e90b | qht132??????|????????3306 | ONLINE???????|
| group_replication_applier | bb0dea82-58ed-11e8-94e5-000c29e8e91b | qht133??????|????????3306 | ONLINE???????|
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)
2.在數據庫端建立proxysql登入需要的帳號(如之前已建立好的話直跳過此步驟)
mysql> CREATE USER 'proxysql'@'%' IDENTIFIED BY 'proxysql'; ? ?
Query OK, 0 rows affected (0.41 sec) ? ?
? ??
mysql> GRANT ALL ON * . * TO??'proxysql'@'%';
Query OK, 0 rows affected (0.00 sec)
? ??
mysql> create user 'sbuser'@'%' IDENTIFIED BY 'sbpass'; ? ?
Query OK, 0 rows affected (0.00 sec) ? ?
? ??
mysql> GRANT ALL ON * . * TO 'sbuser'@'%'; ? ?
Query OK, 0 rows affected (0.00 sec) ? ?
? ??
mysql> FLUSH PRIVILEGES; ? ?
Query OK, 0 rows affected (0.07 sec)?
3.創建檢查MGR節點狀態的函數和視圖
參照前面的博客,在MGR主節點上執行下面鏈接中的SQL
https://github.com/lefred/mysql_gr_routing_check/blob/master/addition_to_sys.sql
USE sys;
?
DELIMITER $$
?
CREATE FUNCTION IFZERO(a INT, b INT)
RETURNS INT
DETERMINISTIC
RETURN IF(a = 0, b, a)$$
?
CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT)
RETURNS INT
DETERMINISTIC
RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$
?
CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000))
RETURNS TEXT(10000)
DETERMINISTIC
RETURN GTID_SUBTRACT(g, '')$$
?
CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000))
RETURNS INT
DETERMINISTIC
BEGIN
? DECLARE result BIGINT DEFAULT 0;
? DECLARE colon_pos INT;
? DECLARE next_dash_pos INT;
? DECLARE next_colon_pos INT;
? DECLARE next_comma_pos INT;
? SET gtid_set = GTID_NORMALIZE(gtid_set);
? SET colon_pos = LOCATE2(':', gtid_set, 1);
? WHILE colon_pos != LENGTH(gtid_set) + 1 DO
? ? ?SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1);
? ? ?SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1);
? ? ?SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1);
? ? ?IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN
? ? ? ?SET result = result +
? ? ? ? ?SUBSTR(gtid_set, next_dash_pos + 1,
? ? ? ? ? ? ? ? LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) -
? ? ? ? ?SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1;
? ? ?ELSE
? ? ? ?SET result = result + 1;
? ? ?END IF;
? ? ?SET colon_pos = next_colon_pos;
? END WHILE;
? RETURN result;
END$$
?
CREATE FUNCTION gr_applier_queue_length()
RETURNS INT
DETERMINISTIC
BEGIN
? RETURN (SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT
Received_transaction_set FROM performance_schema.replication_connection_status
WHERE Channel_name = 'group_replication_applier' ), (SELECT
@@global.GTID_EXECUTED) )));
END$$
?
CREATE FUNCTION gr_member_in_primary_partition()
RETURNS VARCHAR(3)
DETERMINISTIC
BEGIN
? RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((SELECT COUNT(*) FROM
performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >=
((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2) = 0),
'YES', 'NO' ) FROM performance_schema.replication_group_members JOIN
performance_schema.replication_group_member_stats USING(member_id));
END$$
?
CREATE VIEW gr_member_routing_candidate_status AS SELECT
sys.gr_member_in_primary_partition() as viable_candidate,
IF( (SELECT (SELECT GROUP_CONCAT(variable_value) FROM
performance_schema.global_variables WHERE variable_name IN ('read_only',
'super_read_only')) != 'OFF,OFF'), 'YES', 'NO') as read_only,
sys.gr_applier_queue_length() as transactions_behind, Count_Transactions_in_queue as 'transactions_to_cert' from performance_schema.replication_group_member_stats;$$
?
DELIMITER ;
4.在proxysql中增加帳號
????mysql> INSERT INTO MySQL_users(username,password,default_hostgroup) VALUES ('proxysql','proxysql',1);????
Query OK, 1 row affected (0.00 sec) ? ?
mysql> UPDATE global_variables SET variable_value='proxysql' where variable_name='mysql-monitor_username'; ? ?
Query OK, 1 row affected (0.00 sec) ? ?
? ??
mysql> UPDATE global_variables SET variable_value='proxysql' where variable_name='mysql-monitor_password'; ? ?
Query OK, 1 row affected (0.00 sec) ? ?
mysql> LOAD MYSQL SERVERS TO RUNTIME; ?
Query OK, 0 rows affected (0.23 sec) ?
??
mysql> SAVE MYSQL SERVERS TO DISK; ?
Query OK, 0 rows affected (0.08 sec) ?
測試一下能否正常登入數據庫
[root@qht134 proxysql]# mysql -uproxysql -pproxysql -h 127.0.0.1 -P6033 -e"select @@hostname"
mysql: [Warning] Using a password on the command line interface can be insecure.
+------------+
| @@hostname |
+------------+
| qht131?????|
+------------+
5.配置proxysql
?
mysql>??delete from mysql_servers;
Query OK, 6 rows affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(1,'172.17.61.131',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(1,'172.17.61.132',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(1,'172.17.61.133',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(2,'172.17.61.131',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(2,'172.17.61.132',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql>??insert into mysql_servers (hostgroup_id, hostname, port) values(2,'172.17.61.133',3306);
Query OK, 1 row affected (0.00 sec)
?
mysql> select * from??mysql_servers ;
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname??????| port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1????????????| 172.17.61.131 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
| 1????????????| 172.17.61.132 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
| 1????????????| 172.17.61.133 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
| 2????????????| 172.17.61.131 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
| 2????????????| 172.17.61.132 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
| 2????????????| 172.17.61.133 | 3306 | ONLINE | 1??????| 0???????????| 1000????????????| 0???????????????????| 0???????| 0??????????????|?????????|
+--------------+---------------+------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
hostgroup_id = 1代表write group,針對我們提出的限制,這個地方只配置了一個節點;hostgroup_id = 2代表read group,包含了MGR的所有節點,目前只是Onlinle的,等配置過scheduler后,status就會有變化 。
對于上面的hostgroup配置,默認所有的寫操作會發送到hostgroup_id為1的online節點,也就是發送到寫節點上。所有的讀操作,會發送為hostgroup_id為2的online節點。
需要確認一下沒有使用proxysql的讀寫分離規則。因為我昨天配置了這個地方,所以需要刪除,以免影響后面的測試。
mysql> delete from mysql_query_rules;
Query OK, 2 rows affected (0.50 sec)
?
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
最后我們需要將global_variables,mysql_servers、mysql_users表的信息加載到RUNTIME,更進一步加載到DISK:
mysql> LOAD MYSQL VARIABLES TO RUNTIME; ?
Query OK, 0 rows affected (0.00 sec) ?
??
mysql> SAVE MYSQL VARIABLES TO DISK; ?
Query OK, 94 rows affected (0.02 sec) ?
??
mysql> LOAD MYSQL SERVERS TO RUNTIME; ?
Query OK, 0 rows affected (0.00 sec) ?
??
mysql> SAVE MYSQL SERVERS TO DISK; ?
Query OK, 0 rows affected (0.03 sec) ?
??
mysql> LOAD MYSQL USERS TO RUNTIME; ?
Query OK, 0 rows affected (0.00 sec) ?
??
mysql> SAVE MYSQL USERS TO DISK; ?
Query OK, 0 rows affected (0.01 sec) ?
6.配置scheduler
首先,請在Github地址https://github.com/ZzzCrazyPig/proxysql_groupreplication_checker下載相應的腳本
這個地址有三個腳本可供下載:
proxysql_groupreplication_checker.sh:用于multi-primary模式,可以實現讀寫分離,以及故障切換,同一時間點多個節點可以多寫
gr_mw_mode_cheker.sh:用于multi-primary模式,可以實現讀寫分離,以及故障切換,不過在同一時間點只能有一個節點能寫
gr_sw_mode_checker.sh:用于single-primary模式,可以實現讀寫分離,以及故障切換
由于我的環境是multi-primary模式,所以選擇/proxysql_groupreplication_checker.sh腳本。
接著,將我們提供的腳本proxysql_groupreplication_checker.sh放到目錄/var/lib/proxysql/下,并增加可以執行的權限(重要) 。
[root@qht134 ~]# chmod a+x /var/lib/proxysql/proxysql_groupreplication_checker.sh
最后,我們在proxysql的scheduler表里面加載如下記錄,然后加載到RUNTIME使其生效,同時還可以持久化到磁盤:
mysql> INSERT INTO scheduler(id,interval_ms,filename,arg1,arg2,arg3,arg4, arg5)
????-> VALUES (1,'10000','/var/lib/proxysql/proxysql_groupreplication_checker.sh','1','2','1','0','/var/lib/proxysql/proxysql_groupreplication_checker.log');
Query OK, 1 row affected (0.00 sec)
mysql> LOAD SCHEDULER TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
?
mysql> SAVE SCHEDULER TO DISK;
Query OK, 0 rows affected (0.03 sec)
scheduler各column的說明:
active : 1: enable scheduler to schedule the script we provide
interval_ms : invoke one by one in cycle (eg: 5000(ms) = 5s represent every 5s invoke the script)
filename: represent the script file path
arg1~arg5: represent the input parameters the script received
腳本proxysql_groupreplication_checker.sh對應的參數說明如下:
arg1 is the hostgroup_id for write
arg2 is the hostgroup_id for read
arg3 is the number of writers we want active at the same time
arg4 represents if we want that the member acting for writes is also candidate for reads
arg5 is the log file
schedule信息加載后,就會分析當前的環境,mysql_servers中顯示出當前只有qht131是可以寫的,qht132以及qht133是用來讀的。
mysql> ?select * from ?mysql_servers ;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
因為schedule的arg4我設為了0,就表示可寫的節點不能用于讀。那我將arg4設置為1試一下:
mysql> update scheduler set arg4=1;
Query OK, 1 row affected (0.00 sec)
?
mysql> select * from scheduler;
+----+--------+-------------+--------------------------------------------------------+------+------+------+------+---------------------------------------------------------+---------+
| id | active | interval_ms | filename ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? | arg1 | arg2 | arg3 | arg4 | arg5 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?| comment |
+----+--------+-------------+--------------------------------------------------------+------+------+------+------+---------------------------------------------------------+---------+
| 1 ?| 1 ? ? ?| 10000 ? ? ? | /var/lib/proxysql/proxysql_groupreplication_checker.sh | 1 ? ?| 2 ? ?| 1 ? ?| 1 ? ?| /var/lib/proxysql/proxysql_groupreplication_checker.log | ? ? ? ? |
+----+--------+-------------+--------------------------------------------------------+------+------+------+------+---------------------------------------------------------+---------+
1 row in set (0.00 sec)
?
mysql> SAVE SCHEDULER TO DISK;
Query OK, 0 rows affected (0.01 sec)
?
mysql> LOAD SCHEDULER TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
?
mysql> select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------- ? -----------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_repli ? cation_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------- ? -----------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? ? ?| 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------- ? -----------+---------+----------------+---------+
6 rows in set (0.00 sec)
?
arg4設置為1之后,qht131節點用來寫的同時也可以被用來寫。
便于下面的測試還是將arg4設為0:
mysql> ?update scheduler set arg4=0;
Query OK, 1 row affected (0.00 sec)
?
mysql> ?SAVE SCHEDULER TO DISK;
Query OK, 0 rows affected (0.02 sec)
?
mysql> ?LOAD SCHEDULER TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
mysql> ?select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
各個節點的gr_member_routing_candidate_status視圖也顯示了當前節點是否是正常狀態的,proxysql就是讀取的這個視圖的信息來決定此節點是否可用。
mysql> select * from sys.gr_member_routing_candidate_status\G
*************************** 1. row ***************************
? ? viable_candidate: YES
? ? ? ? ? ?read_only: NO
?transactions_behind: 0
transactions_to_cert: 0
1 row in set (0.01 sec)
7.設置讀寫分離:
mysql> insert into mysql_query_rules (active, match_pattern, destination_hostgroup, apply)
? ? -> values (1,"^SELECT",2,1);
Query OK, 1 row affected (0.00 sec)
?
mysql> LOAD MYSQL QUERY RULES TO RUNTIME;
Query OK, 0 rows affected (0.00 sec)
?
mysql> SAVE MYSQL QUERY RULES TO DISK;
Query OK, 0 rows affected (0.03 sec)
match_pattern的規則是基于正則表達式的,
active表示是否啟用這個sql路由項,
match_pattern就是我們正則匹配項,
destination_hostgroup表示我們要將該類sql轉發到哪些mysql上面去,這里我們將select轉發到group 2,。
apply為1表示該正則匹配后,將不再接受其他匹配,直接轉發。
對于for update需要在gruop1上執行,可以加上規則:
insert?into?mysql_query_rules(active,match_pattern,destination_hostgroup,apply)?values(1,'^SELECT.*FOR?UPDATE$',1,1);?
通過一個循環連接proxysql,由于是select 語句,一直連接的是qht132和qht133
[root@qht133 ~]# while true; do mysql -h 172.17.61.134 -u proxysql -pproxysql -P 6033 -e "select @@hostname, sleep(3)" 2>/dev/null; done
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht132 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht133 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht132 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht133 ? ? | ? ? ? ?0 |
+------------+----------+
8.設置故障應用無感應:
在讀寫分離中,我設置了qht131為可寫節點,qht132,qht133為只讀節點
如果此時qht131變成只讀模式的話,應用能不能直接連到其它的節點進行寫操作?
現手動將qht131變成只讀模式:
mysql> set global read_only=1;
Query OK, 0 rows affected (0.00 sec)
觀察一下mysql_servers的狀態,自動將group1的qht132改成了online,group2的qht131,qht133變成online了,就表示將qht132變為可寫節點,其它兩個節點變為只讀節點了。
mysql> select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
通過模擬的連接也可以看到select語句都連接到qht131和qht133進行了。
[root@qht133 ~]# while true; do mysql -h 172.17.61.134 -u proxysql -pproxysql -P 6033 -e "select @@hostname, sleep(3)" 2>/dev/null; done
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht133 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht131 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht133 ? ? | ? ? ? ?0 |
+------------+----------+
+------------+----------+
| @@hostname | sleep(3) |
+------------+----------+
| qht131 ? ? | ? ? ? ?0 |
+------------+----------+
將qht131變為可寫模式后,mysql_servers也恢復過來了。
mysql> set global read_only=0;
Query OK, 0 rows affected (0.00 sec)
mysql> ?select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
經過測試將qht131節點停止組復制(stop group_replication)后,mysql_servers表的信息也會正常的切換新的節點。待qht131再加入到組復制后,mysql_servers也會正常的將qht131改成online狀態。
mysql> select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
容易出現的錯誤:
mysql> ?select * from ?mysql_servers ;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_HARD | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
4 rows in set (0.00 sec)
所有節點都offline了,錯誤日志如下:
[2018-05-22 23:57:52] read node [hostgroup_id: 2, hostname: 172.17.61.133, port: 3306, isOK: 0] is not OK, we will set it's status to be 'OFFLINE_SOFT'
ERROR 1142 (42000) at line 1: SELECT command denied to user 'proxysql'@'qht134' for table 'gr_member_routing_candidate_status'
[2018-05-22 23:57:55] current write node [hostgroup_id: 2, hostname: 172.17.61.131, port: 3306, isOK: 0] is not OK, we need to do switch over
ERROR 1142 (42000) at line 1: SELECT command denied to user 'proxysql'@'qht134' for table 'gr_member_routing_candidate_status'
[2018-05-22 23:57:55] read node [hostgroup_id: 2, hostname: 172.17.61.132, port: 3306, isOK: 0] is not OK, we will set it's status to be 'OFFLINE_SOFT'
ERROR 1142 (42000) at line 1: SELECT command denied to user 'proxysql'@'qht134' for table 'gr_member_routing_candidate_status'
從錯誤日志上看出是權限的問題,proxysql用戶沒有足夠的權限讀取數據。
解決:
mysql> GRANT ALL ON * . * TO??'proxysql'@'%'; ?mysql> flush privileges;
mysql> ?select * from ?mysql_servers;
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname ? ? ?| port | status ? ? ? | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1 ? ? ? ? ? ?| 172.17.61.131 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.132 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 1 ? ? ? ? ? ?| 172.17.61.133 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.131 | 3306 | OFFLINE_SOFT | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.132 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
| 2 ? ? ? ? ? ?| 172.17.61.133 | 3306 | ONLINE ? ? ? | 1 ? ? ?| 0 ? ? ? ? ? | 1000 ? ? ? ? ? ?| 0 ? ? ? ? ? ? ? ? ? | 0 ? ? ? | 0 ? ? ? ? ? ? ?| ? ? ? ? |
+--------------+---------------+------+--------------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
6 rows in set (0.00 sec)
參考:
http://lefred.be/content/ha-with-mysql-group-replication-and-proxysql/
https://blog.csdn.net/d6619309/article/details/54602556
---------------------?
作者:zuozhiji?
來源:CSDN?
原文:https://blog.csdn.net/jolly10/article/details/80415685?
版權聲明:本文為博主原創文章,轉載請附上博文鏈接!
總結
以上是生活随笔為你收集整理的MySQL用中间件ProxySQL实现读写分离和主节点故障应用无感应的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MySQL 使用 LOAD DATA 导
- 下一篇: navicat 导入SQL文件出错