ProxySQL路由及代理多組MGR

ProxySQL路由及代理多組MGR

文章來源: 陶老師運維筆記- 微信公衆號html

1. 背景介紹

ProxySQL代理MGR:前端

ProxySQL 是一個較輕量但功能強大的MySQL中間件。能夠很好的支持 Master Slave, MGR, PXC等MySQL架構,並提供鏈接池、讀寫分離、日誌記錄等功能。mysql

MySQL Group Replication(簡稱MGR)複製技術解決了數據一致性問題。可是當Master 宕機,應用系統可能仍須要修改數據庫主庫鏈接地址,才能保證服務的可用性:( 爲解決此問題,我們能夠在MRG上層增長一Proxy代理層。git

前文已介紹了ProxySQL代理一個MGR (陶老師運維筆記- MySQL中間件 ProxySQL代理MGR),本節介紹如何用一個ProxySQL代理多組MGR。github

2. 測試環境

2.1 環境規劃

準備DB及Proxy機器,將規劃以下:正則表達式

角色 版本 IP port server-id hostgroup
Proxy-1 2.0.8 192.110.154.98 6032/6033 - -
mgr01-1 MySQL5.7.23 192.110.103.41 3106 103413106 1000
mgr01-2 MySQL5.7.23 192.110.103.42 3106 103423106 1000
mgr01-3 MySQL5.7.23 192.110.103.43 3106 103433106 1000
mgr02-1 MySQL5.7.23 192.110.103.41 3107 103413107 2000
mgr02-2 MySQL5.7.23 192.110.103.42 3107 103423107 2000
mgr02-3 MySQL5.7.23 192.110.103.43 3107 103433107 2000

3. MGR安裝

依安裝參考完成mgr01,mgr02集羣的安裝。sql

MGR集羣信息:數據庫

  • mgr01機羣 : 192.110.103.41/42/43,Port:3106。MGR爲單主模式,mgr01-1爲Master。
  • mgr02機羣 : 192.110.103.41/42/43,Port:3107。MGR爲單主模式, mgr02-1爲Master。
#mgr01 3106
192.110.103.41 : (none) > SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST   | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| group_replication_applier | 509810ee-f3d7-11e9-a7d5-a0369fac2de4 | 192.110.103.41 |        3106 | ONLINE       |
| group_replication_applier | 74eedba2-2314-11ea-9146-a0369fa6cce4 | 192.110.103.42 |        3106 | ONLINE       |
| group_replication_applier | ee4a9cec-f3d5-11e9-9ded-a0369fa6cd30 | 192.110.103.43 |        3106 | ONLINE       |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
3 rows in set (0.00 sec)

# mgr02 3107
192.110.103.41 : (none) >  SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST   | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
| group_replication_applier | 39379630-1e74-11ea-b98b-a0369fac2de4 | 192.110.103.41 |        3107 | ONLINE       |
| group_replication_applier | 47aa5d94-1e74-11ea-834a-a0369fa6cce4 | 192.110.103.42 |        3107 | ONLINE       |
| group_replication_applier | 4bf4a2cb-1e74-11ea-8d6e-a0369fa6cd30 | 192.110.103.43 |        3107 | ONLINE       |
+---------------------------+--------------------------------------+---------------+-------------+--------------+
3 rows in set (0.00 sec)
複製代碼

4. Proxy安裝

下載
$wget https://github.com/sysown/proxysql/releases/download/v2.0.8/proxysql-2.0.8-1-centos67.x86_64.rpm
#安裝
$rpm -ivh proxysql-2.0.8-1-centos67.x86_64.rpm 
#查看版本
$proxysql --version
ProxySQL version 2.0.8-67-g877cab1, codename Truls
複製代碼

5. Proxy路由知識

5.1 路由方法介紹

ProxySQL能夠實現多種方式的路由:基於ip/port、username、schema、SQL語句。後端

當ProxySQL收到前端app發送的SQL語句後,它須要將這個SQL語句(或者重寫後的SQL語句)發送給後端的MySQL Server,而後收到SQL語句的MySQL Server執行查詢,並將查詢結果返回給ProxySQL,再由ProxySQL將結果返回給客戶端(若是設置了查詢緩存,則先緩存查詢結果)。centos

5.2 mysql_query_rules 表

mysql -uadmin -padmin -P6032 -h127.0.0.1 --prompt 'admin> '      
show create table mysql_query_rules\G
#mysql_query_rules表結構
|       COLUMN          |  TYPE   |  NULL?   | DEFAULT    |
|-----------------------|---------|----------|------------|
| rule_id   (pk)        | INTEGER | NOT NULL |            |
| active                | INT     | NOT NULL | 0          |
| username              | VARCHAR |          |            |
| schemaname            | VARCHAR |          |            |
| flagIN                | INT     | NOT NULL | 0          |
| client_addr           | VARCHAR |          |            |
| proxy_addr            | VARCHAR |          |            |
| proxy_port            | INT     |          |            |
| digest                | VARCHAR |          |            |
| match_digest          | VARCHAR |          |            |
| match_pattern         | VARCHAR |          |            |
| negate_match_pattern  | INT     | NOT NULL | 0          |
| re_modifiers          | VARCHAR |          | 'CASELESS' |
| flagOUT               | INT     |          |            |
| replace_pattern       | VARCHAR |          |            |
| destination_hostgroup | INT     |          | NULL       |
| cache_ttl             | INT     |          |            |
| reconnect             | INT     |          | NULL       |
| timeout               | INT     |          |            |
| retries               | INT     |          |            |
| delay                 | INT     |          |            |
| mirror_flagOU         | INT     |          |            |
| mirror_hostgroup      | INT     |          |            |
| error_msg             | VARCHAR |          |            |
| sticky_conn           | INT     |          |            |
| multiplex             | INT     |          |            |
| log                   | INT     |          |            |
| apply                 | INT     | NOT NULL | 0          |
| comment               | VARCHAR |          |            |

#查看規則
select * from mysql_query_rules\G
複製代碼

主要字段的意義以下:

  • rule_id:規則的id。規則是按照rule_id的順序進行處理的
  • active:只有該值爲1的規則纔會加載到runtime數據結構,這些規則纔會被查詢處理模塊處理。
  • username:用戶名篩選,當爲非NULL值時,只有匹配的用戶創建的鏈接發出的查詢纔會被匹配。
  • schemaname:schema篩選,當爲非NULL值時,只有當鏈接使用schemaname做爲默認schema時,該鏈接發出的查詢纔會被匹配。
  • flagIN,flagOUT:這些字段容許咱們建立"鏈式規則"(chains of rules),一個規則接一個規則。
  • apply:當匹配到該規則時,當即應用該規則。
  • client_addr:經過源地址進行匹配。
  • proxy_addr:當流入的查詢是在本地某地址上時,將匹配。
  • proxy_port:當流入的查詢是在本地某端口上時,將匹配。
  • digest:經過digest進行匹配,digest的值在stats_mysql_query_digest.digest中。
  • match_digest:經過正則表達式匹配digest。
  • match_pattern:經過正則表達式匹配查詢語句的文本內容。
  • delay:延遲執行該查詢的毫秒數。是一限流機制和QoS,使得可將優先級讓位於其它查詢。
  • apply:當設置爲1後,當匹配到該規則後,將當即應用該規則,不會再評估其它的規則.

5.3 路由統計相關表

在stat統計庫中有些表和路由相關(stats_mysql_query_rules,stats_mysql_query_digest,stats_mysql_query_digest_reset)。 詳細介紹見本文查看統計/監控信息節。

show table from stats;
複製代碼

6. Proxy配置

6.1 配置後端DB主機

提早規劃好,MGR01集羣group爲1000,MRG02爲2000。

mysql -uadmin -padmin -P6032 -h127.0.0.1 --prompt 'admin>'
#配置後端DB
select * from mysql_servers;
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(1000,2000,'MGR01-01','192.110.103.41',3106);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(1000,2000,'MGR01-02','192.110.103.42',3106);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(1000,2000,'MGR01-03','192.110.103.43',3106);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(2000,2000,'MGR02-01','192.110.103.41',3107);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(2000,2000,'MGR02-02','192.110.103.42',3107);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(2000,2000,'MGR02-03','192.110.103.43',3107);
select hostgroup_id,hostname,port,status,weight from mysql_servers;
#配置生效
load mysql servers to runtime;
save mysql servers to disk;
#檢查
select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;
select hostgroup_id,hostname,port,status,weight,comment from runtime_mysql_servers;
+--------------+---------------+------+--------+--------+----------+
| hostgroup_id | hostname      | port | status | weight | comment  |
+--------------+---------------+------+--------+--------+----------+
| 1000         | 192.110.103.41 | 3106 | ONLINE | 1      | MGR01-01 |
| 1000         | 192.110.103.42 | 3106 | ONLINE | 1      | MGR01-02 |
| 1000         | 192.110.103.43 | 3106 | ONLINE | 1      | MGR01-03 |
| 2000         | 192.110.103.41 | 3107 | ONLINE | 1      | MGR02-01 |
| 2000         | 192.110.103.42 | 3107 | ONLINE | 1      | MGR02-02 |
| 2000         | 192.110.103.43 | 3107 | ONLINE | 1      | MGR02-03 |
+--------------+---------------+------+--------+--------+----------+
複製代碼

6.2 配置監控帳號

ProxySQL須要監控後端節點的狀態權限,由於ProxySQL須要監控DB只讀read_only等狀態信息。

MySQL增長帳號:

#MySQL Master
create user monitor@'%' identified by 'P@ssword1!';
grant select on sys.* to monitor@'%';
grant replication client on *.* to monitor@'% ' identified by 'P@ssword1!'; 
複製代碼

ProxySQL上配置監控:

#proxy
set mysql-monitor_username='monitor'; set mysql-monitor_password='P@ssword1!';
#檢查
select * from global_variables where variable_name like 'mysql-monitor%'; 
#檢查ping 
SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10;  
#mysql_server_connect_log
SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 6; 
#生效,能夠等DB健康檢查ok後再生效。
load mysql variables to runtime;
save mysql variables to disk;
複製代碼

配置各類監控的時間間隔:(可略)

UPDATE global_variables SET variable_value='2000' WHERE variable_name IN ('mysql-monitor_connect_interval','mysql-monitor_ping_interval','mysql-monitor_read_only_interval');
複製代碼

6.3 後端DB健康檢查

配置監控帳號後,可對後端DB作健康檢查,肯定ProxySQL是否能和這些後端節點通訊。proxy對connect和ping的監控是基於mysql_servers表的內容執行的,甚至是在其加載到RUNTIME以前。

show tables from monitor;
+--------------------------------------+
| tables                               |
+--------------------------------------+
| mysql_server_aws_aurora_check_status |
| mysql_server_aws_aurora_failovers    |
| mysql_server_aws_aurora_log          |
| mysql_server_connect_log             |
| mysql_server_galera_log              |
| mysql_server_group_replication_log   |
| mysql_server_ping_log                |
| mysql_server_read_only_log           |
| mysql_server_replication_lag_log     |
+--------------------------------------+

#ping 
SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 10;  
#mysql_server_connect_log
SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 3; 
+---------------+------+------------------+-------------------------+---------------+
| hostname      | port | time_start_us    | connect_success_time_us | connect_error |
+---------------+------+------------------+-------------------------+---------------+
| 192.110.103.42 | 3106 | 1577692274817162 | 733                     | NULL          |
| 192.110.103.41 | 3107 | 1577692274469387 | 653                     | NULL          |
| 192.110.103.43 | 3106 | 1577692274121636 | 836                     | NULL          |
+---------------+------+------------------+-------------------------+---------------+

複製代碼

由上表知道了全部的節點都被合理監控且它們都正常,如今啓用它們。

#生效
load mysql variables to runtime;
save mysql variables to disk;
複製代碼

6.4 錄入MySQL複製組信息

MySQL組複製(MGR)或者InnoDB Cluster,使用mysql_group_replication_hostgroups表。

如果傳統的異步、半同步主從複製主機組,使用mysql_replication_hostgroups表來定義。該表指定該表中的組哪些是寫組,哪些是讀組。

6.4.1 MGR複製組

mysql_group_replication_hostgroups: 插入讀/寫組的信息到表中。如mgr01,1000爲寫組,1002爲讀組。

#proxySQL中insert 數據
insert into mysql_group_replication_hostgroups(writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,active,max_writers,writer_is_also_reader,max_transactions_behind,comment) 
values(1000,1001,1002,1003,1,1,0,10,'cluster-mgr01');
#如果多個mgr能夠再次insert
insert into mysql_group_replication_hostgroups(writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,active,max_writers,writer_is_also_reader,max_transactions_behind,comment) 
values(2000,2001,2002,2003,1,1,0,10,'cluster-mgr02');

複製代碼

上述配置中,本例中writer_is_also_reader設置爲false,則master只負責寫操做。

配置生效:

load mysql servers to runtime;
save mysql servers to disk;
查看錄入結果
admin> select writer_hostgroup,backup_writer_hostgroup,reader_hostgroup,offline_hostgroup,active,writer_is_also_reader,comment 
 from runtime_mysql_group_replication_hostgroups;
+------------------+-------------------------+------------------+-------------------+--------+-----------------------+---------------+
| writer_hostgroup | backup_writer_hostgroup | reader_hostgroup | offline_hostgroup | active | writer_is_also_reader | comment       |
+------------------+-------------------------+------------------+-------------------+--------+-----------------------+---------------+
| 1000             | 1001                    | 1002             | 1003              | 1      | 0                     | cluster-mgr01 |
| 2000             | 2001                    | 2002             | 2003              | 1      | 0                     | cluster-mgr02 |
+------------------+-------------------------+------------------+-------------------+--------+-----------------------+---------------+
2 rows in set (0.00 sec)

查看實時服務器狀態
select hostgroup_id, hostname, port,status from runtime_mysql_servers;

查看檢測MGR節點狀態
select hostname,port,viable_candidate,read_only,transactions_behind,error
from mysql_server_group_replication_log order by time_start_us desc limit 10;
select * from mysql_server_group_replication_log order by time_start_us desc limit 3; 
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
| hostname      | port | time_start_us    | success_time_us | viable_candidate | read_only | transactions_behind | error |
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
| 192.110.103.43 | 3106 | 1577540023301725 | 2288            | YES              | YES       | 0                   | NULL  |
| 192.110.103.42 | 3106 | 1577540023301423 | 2821            | YES              | YES       | 0                   | NULL  |
| 192.110.103.41 | 3106 | 1577540023301088 | 2563            | YES              | NO        | 0                   | NULL  |
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
3 rows in set (0.00 sec)

#
admin> SELECT * FROM mysql_replication_hostgroups;
Empty set (0.00 sec)
複製代碼

6.4.2 傳統M/S複製組及read_only識別

mysql_replication_hostgroups:

定義傳統的異步、半同步主從複製主機組。配置後將會檢查read_only,並調整mysql_servers。(本次雖然是測試proxy代理MGR,可是mysql_replication_hostgroups表可用來自動調整讀寫group,故仍進行了配置)。

向mysql_replication_hostgroups表中寫入信息,注意讀/寫組須要和mysql_group_replication_hostgroups相一致。load mysql_replication_hostgroupsg表信息後,proxy將會檢查read_only,並自動調整mysql_servers。以下測試可見mgr01從庫的hostgroup_id將由1000變爲了1002。

select * from runtime_mysql_servers;
SHOW CREATE TABLE mysql_replication_hostgroups\G
SELECT * FROM mysql_replication_hostgroups;
SELECT * FROM runtime_mysql_group_replication_hostgroups;
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------------+
| writer_hostgroup | backup_writer_hostgroup | reader_hostgroup | offline_hostgroup | active | max_writers | writer_is_also_reader | max_transactions_behind | comment       |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------------+
| 1000             | 1001                    | 1002             | 1003              | 1      | 1           | 0                     | 10                      | cluster-mgr01 |
| 2000             | 2001                    | 2002             | 2003              | 1      | 1           | 0                     | 10                      | cluster-mgr02 |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------------+

#注意mysql_replication_hostgroup信息讀/寫組和mysql_group_replication_hostgroups相一致
#proxy 2.x版本 , 
insert into mysql_replication_hostgroups values(1000,1002,'read_only','mgr01'); 
insert into mysql_replication_hostgroups values(2000,2002,'read_only','mgr02');

select * from runtime_mysql_replication_hostgroups;
+------------------+------------------+------------+---------+
| writer_hostgroup | reader_hostgroup | check_type | comment |
+------------------+------------------+------------+---------+
| 1000             | 1002             | read_only  | mgr01   |
| 2000             | 2002             | read_only  | mgr02   |
+------------------+------------------+------------+---------+
2 rows in set (0.00 sec)

#將剛纔mysql_replication_hostgroups表的修改加載到RUNTIME生效。
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;

SELECT * FROM monitor.mysql_server_read_only_log ORDER BY time_start_us DESC LIMIT 6;
+---------------+------+------------------+-----------------+-----------+-------+
| hostname      | port | time_start_us    | success_time_us | read_only | error |
+---------------+------+------------------+-----------------+-----------+-------+
| 192.110.103.42 | 3106 | 1577933427754071 | 267             | 1         | NULL  |
| 192.110.103.41 | 3107 | 1577933427747356 | 312             | 0         | NULL  |
| 192.110.103.42 | 3107 | 1577933427740627 | 263             | 1         | NULL  |
| 192.110.103.43 | 3106 | 1577933427733875 | 200             | 1         | NULL  |
| 192.110.103.43 | 3107 | 1577933427727149 | 291             | 1         | NULL  |
| 192.110.103.41 | 3106 | 1577933427720446 | 242             | 0         | NULL  |
+---------------+------+------------------+-----------------+-----------+-------+
6 rows in set (0.00 sec)

# load mysql_replication_hostgroups後,將會檢查read_only,並調整mysql_servers。
# 以下可見從庫的hostgroup_id由1000變爲了1002。

admin> select * from runtime_mysql_servers;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment  |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 1000         | 192.110.103.41 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-01 |
| 2002         | 192.110.103.42 | 3107 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR02-02 |
| 2002         | 192.110.103.43 | 3107 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR02-03 |
| 1002         | 192.110.103.42 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-02 |
| 1002         | 192.110.103.43 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-03 |
| 2000         | 192.110.103.41 | 3107 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR02-01 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
6 rows in set (0.00 sec)
複製代碼

6.5 配置mysql_users

在DB Master節點上執行:

#MySQL Master, 可依用戶名來區分多組DB,來實現路由
#mgr01組
grant select,insert,update,delete on *.* to 'mgr01'@'%' identified by 'P@ssword1!';
grant all on *.* to mgr01_root@'%' identified by 'P@ssword1!';
flush privileges;
192.110.103.41 : (none) > select user,host,authentication_string from mysql.user where user like 'mgr%';   
+------------+------+-------------------------------------------+
| user       | host | authentication_string                     |
+------------+------+-------------------------------------------+
| mgr01      | %    | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 |
| mgr01_root | %    | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 |
+------------+------+-------------------------------------------+
2 rows in set (0.00 sec)

#mgr02組
grant select,insert,update,delete on *.* to 'mgr02'@'%' identified by 'P@ssword1!';
grant all on *.* to mgr02_root@'%' identified by 'P@ssword1!';
select user,host,authentication_string from mysql.user where user like 'mgr%';   
+------------+------+-------------------------------------------+
| user       | host | authentication_string                     |
+------------+------+-------------------------------------------+
| mgr02      | %    | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 |
| mgr02_root | %    | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 |
+------------+------+-------------------------------------------+
複製代碼

proxysql配置:

#proxy v2.0.8

#沒有配置mysql_query_rules;
select * from mysql_query_rules;
Empty set (0.00 sec)
admin> select * from runtime_mysql_query_rules;
Empty set (0.00 sec)

select * from mysql_users;
#delete from mysql_users;
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr01','P@ssword1!',1000,1);
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr01_root','P@ssword1!',1000,1);
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr02','P@ssword1!',2000,1);
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr02_root','P@ssword1!',2000,1);
select username,password,active,default_hostgroup,transaction_persistent,fast_forward,frontend,comment from mysql_users;                
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+
| username   | password   | active | default_hostgroup | transaction_persistent | fast_forward | frontend | comment |
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+
| mgr01      | P@ssword1! | 1      | 1000              | 1                      | 0            | 1        |         |
| mgr01_root | P@ssword1! | 1      | 1000              | 1                      | 0            | 1        |         |
| mgr02      | P@ssword1! | 1      | 2000              | 1                      | 0            | 1        |         |
| mgr02_root | P@ssword1! | 1      | 2000              | 1                      | 0            | 1        |         |
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+
#
load mysql users to runtime;
save mysql users to disk;
複製代碼

username 和 password字段的意義很明顯。default_hostgroup字段是默認的路由目標主機組,當該用戶發出的查詢語句沒有匹配到任何查詢規則時,該查詢語句將路由到該字段指定的默認組中的節點

說明:

  • 注意hostgroup要和mysql_servers中的組相一致,comment作爲備註爲MGR01機羣。
  • 爲不一樣的MGR組定義了不一樣的用戶名,如mgr01,mgr02.可方便經過用戶名來路由不一樣的DB集羣

7. 路由測試

7.1 用username來路由

我們來測試下未配置mysql_query_rules路由表的狀況下,只使用用戶名及default_hostgroup來路由是否合預期

mgr01/mgr02組MySQL建立測試表:

#在mgr01_master上建立測試表
drop table if exists test.t1;
CREATE TABLE test.t1 (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB ; 

#在mgr02_master上建立測試表
drop table if exists test.t2;
CREATE TABLE test.t2 (
  `id` int(10) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  ctime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB ; 
複製代碼

當前proxy配置狀況: 沒有配置mysql_query_rules規則。

#檢查mysql_query_rules規則,沒有配置;
admin> select * from mysql_query_rules;
Empty set (0.00 sec)
admin> select * from runtime_mysql_query_rules;
Empty set (0.00 sec)
select username,password,active,default_hostgroup,transaction_persistent,fast_forward,frontend,comment from mysql_users;                
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+
| username   | password   | active | default_hostgroup | transaction_persistent | fast_forward | frontend | comment |
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+
| mgr01      | P@ssword1! | 1      | 1000              | 1                      | 0            | 1        |         |
| mgr01_root | P@ssword1! | 1      | 1000              | 1                      | 0            | 1        |         |
| mgr02      | P@ssword1! | 1      | 2000              | 1                      | 0            | 1        |         |
| mgr02_root | P@ssword1! | 1      | 2000              | 1                      | 0            | 1        |         |
+------------+------------+--------+-------------------+------------------------+--------------+----------+---------+

複製代碼

測試讀/寫:

測試未配置mysql_query_rules路由表的狀況下,只使用不一樣用戶名mgr01/mgr02是否能夠正確的路由。

#測試mgr01讀/寫
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; "
+-------------+
| @@server_id |
+-------------+
|   103413106 |
+-------------+
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "start transaction;select @@server_id;commit;"
+-------------+
| @@server_id |
+-------------+
|   103423106 |
+-------------+

#測試mgr02讀/寫
mysql -umgr02 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; "
+-------------+
| @@server_id |
+-------------+
|   103423107 |
+-------------+
 mysql -umgr02 -pP@ssword1! -P6033 -h127.0.0.1 test -e "insert into test.t2(name) values(now());select @@server_id; "   

admin> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest order by last_seen desc limit 6;
+-----------+------------+----------+-----------------------------------------+
| hostgroup | schemaname | username | digest_text                             |
+-----------+------------+----------+-----------------------------------------+
| 2000      | test       | mgr02    | insert into test.t2(name) values(now()) |
| 2000      | test       | mgr02    | select @@server_id                      |
| 2000      | test       | mgr02    | select @@version_comment limit ?        |
| 2000      | test       | mgr02    | select * from test.t2                   |
| 1000      | test       | mgr01    | select @@version_comment limit ?        |
| 1000      | test       | mgr01    | select @@server_id                      |
+-----------+------------+----------+-----------------------------------------+
6 rows in set (0.01 sec)

複製代碼

能夠看到mgr01/mgr02都正確的讀寫了數據,測試合預期。

7.2 讀寫分離及路由

上述簡單用username來路由,並無可以實現讀寫分離,讀寫組都是依mysql_user表中的default_group,即便用1000,2000組

admin> select * from mysql_users;
+------------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| username   | password   | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections | comment |
+------------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| mgr01      | P@ssword1! | 1      | 0       | 1000              | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |         |
| mgr01_root | P@ssword1! | 1      | 0       | 1000              | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |         |
| mgr02      | P@ssword1! | 1      | 0       | 2000              | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |         |
| mgr02_root | P@ssword1! | 1      | 0       | 2000              | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |         |
+------------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
4 rows in set (0.00 sec)

admin> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest order by last_seen desc limit 6;
+-----------+------------+----------+-----------------------------------------+
| hostgroup | schemaname | username | digest_text                             |
+-----------+------------+----------+-----------------------------------------+
| 2000      | test       | mgr02    | insert into test.t2(name) values(now()) |
| 2000      | test       | mgr02    | select @@server_id                      |
| 2000      | test       | mgr02    | select @@version_comment limit ?        |
| 2000      | test       | mgr02    | select * from test.t2                   |
| 1000      | test       | mgr01    | select @@version_comment limit ?        |
| 1000      | test       | mgr01    | select @@server_id                      |
+-----------+------------+----------+-----------------------------------------+
6 rows in set (0.01 sec)
複製代碼

爲解決此問題,我們要配置mysql_query_rules表。

mysql_query_rules:

mysql_query_rules表中有多個字段,它們可以方便的控制每一個查詢請求如何經過ProxySQL進行路由。較重要的用username,schemaname,match_digest等。其中match_digest是對digest作正則匹配,但注意match_pattern字段中給的規則不是hash值,而是SQL語句的文本匹配規則

#show create table mysql_query_rules\G
select * from runtime_mysql_servers where port=3106;
admin> select * from mysql_query_rules;
Empty set (0.00 sec)

#mgr01
INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (100,1,'mgr01.*','^SELECT.*FOR UPDATE$',1000,1);
INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (101,1,'mgr01.*','^SELECT',1002,1);
#mgr02
INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (200,1,'mgr02','^SELECT.*FOR UPDATE$',2000,1);
INSERT INTO mysql_query_rules (rule_id,active,username,match_digest,destination_hostgroup,apply) VALUES (201,1,'mgr02','^SELECT',2002,1);

select rule_id,active,username,schemaname,client_addr,proxy_addr,proxy_port,match_digest,destination_hostgroup,apply,retries from mysql_query_rules;
+---------+--------+----------+------------+-------------+------------+------------+----------------------+-----------------------+-------+---------+
| rule_id | active | username | schemaname | client_addr | proxy_addr | proxy_port | match_digest         | destination_hostgroup | apply | retries |
+---------+--------+----------+------------+-------------+------------+------------+----------------------+-----------------------+-------+---------+
| 100     | 1      | mgr01*   | NULL       | NULL        | NULL       | NULL       | ^SELECT.*FOR UPDATE$ | 1000                  | 1     | NULL    |
| 101     | 1      | mgr01*   | NULL       | NULL        | NULL       | NULL       | ^SELECT              | 1002                  | 1     | NULL    |
+---------+--------+----------+------------+-------------+------------+------------+----------------------+-----------------------+-------+---------+
2 rows in set (0.00 sec)
select  * from runtime_mysql_query_rules\G;
load mysql query rules to runtime;
save mysql query rules to disk;
#查看語句路由狀態:
select hostgroup,digest_text from stats_mysql_query_digest;  

複製代碼

測試讀寫分離:

#mgr01
for((i=0;i<1000;i++)) do echo $i; mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; " ; sleep 0.5; done;
+-------------+
| @@server_id |
+-------------+
|   103413106 |
+-------------+
#mgr02
for((i=0;i<1000;i++)) do echo $i; mysql -umgr02 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; " ; sleep 0.5; done; 
0
+-------------+
| @@server_id |
+-------------+
|   103423107 |
+-------------+
複製代碼

說明

  • mysql_query_rules的規則較mysql_group_replication_hostgroups的優先級高。
  • 從結果上看mgr02成功實現了讀寫分離,可是mgr01的讀還是使用了主庫。看上去用戶名來路由不支持正則?有待進一步研究下。

7.3 有同名用戶的路由

前面測試了依mysql username來進行簡單路由。但如果不一樣組MGR有相同的用戶名,哪要如何來實現呢? 我們可經過對mysql_query_rules進行配置,如依username+ schemaname或username+clientip的組合,作爲路由key來進行訪問路由。

MGR01/MGR02增長同名帳號:

#mgr01/mgr02 MySQL Master 上執行
create user guest@'%' identified by 'P@ssword1!';
grant select,insert,update,delete on *.* to guest@'%';

#mgr01建庫test_01
192.110.103.41:3106 : test > create database  if not exists test_01 ;   
#mgr02建庫test_02
192.110.103.41:3107 : test > create database  if not exists test_02;   
複製代碼

proxysql配置:

#default_hostgroup爲0
insert into mysql_users(username,password,transaction_persistent) values('guest','P@ssword1!',1);
select * from mysql_users where username='guest';
+----------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| username | password   | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections | comment |
+----------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
| guest    | P@ssword1! | 1      | 0       | 0                 | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |         |
+----------+------------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+---------+
load mysql users to runtime;
save mysql users to disk;
複製代碼

此時由於沒有配置default_hostgroup,我們guest用戶實際是不可用的,以下。

mysql -uguest -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; " ; 
ERROR 9001 (HY000) at line 1: Max connect timeout reached while reaching hostgroup 0 after 10001ms
複製代碼

配置mysql_query_rules:

把username+ schemaname作爲路由key來配置mysql_query_rules表。

#show create table mysql_query_rules\G
select * from runtime_mysql_servers ;
select * from mysql_query_rules;

#mgr01
INSERT INTO mysql_query_rules (rule_id,active,username,schemaname,destination_hostgroup,apply) VALUES (102,1,'guest','test_01',1000,1);
#mgr02
INSERT INTO mysql_query_rules (rule_id,active,username,schemaname,destination_hostgroup,apply) VALUES (202,1,'guest','test_02',2000,1);


select rule_id,active,username,schemaname,client_addr,proxy_addr,proxy_port,match_digest,destination_hostgroup,apply,retries from mysql_query_rules where username='guest';
+---------+--------+----------+------------+-------------+------------+------------+--------------+-----------------------+-------+---------+
| rule_id | active | username | schemaname | client_addr | proxy_addr | proxy_port | match_digest | destination_hostgroup | apply | retries |
+---------+--------+----------+------------+-------------+------------+------------+--------------+-----------------------+-------+---------+
| 102     | 1      | guest    | test_01    | NULL        | NULL       | NULL       | NULL         | 1000                  | 1     | NULL    |
| 202     | 1      | guest    | test_02    | NULL        | NULL       | NULL       | NULL         | 2000                  | 1     | NULL    |
+---------+--------+----------+------------+-------------+------------+------------+--------------+-----------------------+-------+---------+
2 rows in set (0.00 sec)
select  * from runtime_mysql_query_rules\G;
load mysql query rules to runtime;
save mysql query rules to disk;
#查看語句路由狀態:
select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest order by last_seen desc limit 6;

複製代碼

測試同名帳戶狀況下的路由:

#mgr01
 mysql -uguest -pP@ssword1! -P6033 -h127.0.0.1 test_01 -e " select @@server_id"
+-------------+
| @@server_id |
+-------------+
|   103413106 |
+-------------+
#mgr02
 mysql -uguest -pP@ssword1! -P6033 -h127.0.0.1 test_02 -e " select @@server_id"
+-------------+
| @@server_id |
+-------------+
|   103413107 |
+-------------+
複製代碼

由結果可見username+dbname作爲路由key,能夠正常的路由讀寫。 但要特別注意: 由於沒有設置default_hostgroup,如果client訪問ProxySQL,未寫dbname或寫錯dbname將沒法路由,訪問出錯。故不一樣的mgr,用戶名儘可能不要相同,會更好運維些。

#沒有正確寫dbname示例
mysql -uguest -pP@ssword1! -P6033 -h127.0.0.1 test -e " select @@server_id"   
ERROR 9001 (HY000) at line 1: Max connect timeout reached while reaching hostgroup 0 after 10000ms
# mysql -uguest -pP@ssword1! -P6033 -h127.0.0.1 t -e " select @@server_id" 
ERROR 9001 (HY000) at line 1: Max connect timeout reached while reaching hostgroup 0 after 10000ms

admin> select hostgroup,schemaname,username,digest_text,client_address,last_seen from stats_mysql_query_digest order by last_seen desc limit 3;
+-----------+------------+----------+----------------------------------+----------------+------------+
| hostgroup | schemaname | username | digest_text                      | client_address | last_seen  |
+-----------+------------+----------+----------------------------------+----------------+------------+
| 0         | test_02    | guest    | select @@version_comment limit ? |                | 1577962135 |
| 2000      | test_02    | guest    | select @@server_id               |                | 1577962135 |
| 1000      | test_01    | guest    | select @@server_id               |                | 1577962117 |
+-----------+------------+----------+----------------------------------+----------------+------------+
5 rows in set (0.01 sec)
複製代碼

8. 查看統計/監控信息

8.1 統計表信息

ProxySQL會把一些統計數據放到stats庫的表中。

#統計信息表
admin> show tables from stats;
+--------------------------------------+
| tables                               |
+--------------------------------------+
| global_variables                     |
| stats_memory_metrics                 |
| stats_mysql_commands_counters        |     <--已執行查詢語句的統計信息
| stats_mysql_connection_pool          |     <--鏈接池信息
| stats_mysql_connection_pool_reset    |     <--重置鏈接池統計數據
| stats_mysql_global                   |     <--全局統計數據
| stats_mysql_prepared_statements_info |
| stats_mysql_processlist              |     <--模擬show processlist的結果
| stats_mysql_query_digest             |   <--記錄各種查詢相關統計數據
| stats_mysql_query_digest_reset       |   <--查詢統計數據表
| stats_mysql_query_rules              |   <--規則被查詢語句匹配的次數
| stats_mysql_users                    |     <--各mysql user前端和ProxySQL的鏈接數
| stats_proxysql_servers_checksums     |     <--ProxySQL集羣相關
| stats_proxysql_servers_metrics       |     <--ProxySQL集羣相關
| stats_proxysql_servers_status        |     <--ProxySQL集羣相關
+--------------------------------------+

複製代碼

統計庫中的路由相關表:

  • stats_mysql_query_rules - 每一個查詢規則被查詢語句匹配的次數。
  • stats_mysql_query_digest - 該表包含經過ProxySQL路由出去的各種查詢相關統計數據。查詢的類指的是參數相同,?值不一樣的查詢。
  • stats_mysql_query_digest_reset - 和stats_mysql_query_digest徹底一致,但查詢它時會自動將內部統計數據重置爲0。
  • stats_mysql_connection_pool 存後端節點的鏈接池使用狀況相關的統計數據。
  • stats_mysql_commands_counters 存SQL命令(例如UPDATE, DELETE等)已執行次數等信息。
  • stats_mysql_processlist 存相似MySQL命令"SHOW PROCESSLIST"結果的表。

stats.stats_mysql_connection_pool:

該表中記錄了大量和發送到每一個後端節點相關查詢請求的信息。正如預料的結果,全部的寫查詢都發送給了hostgroup 1中監聽在1000,2000的節點,它們是master節點。

admin> SELECT * FROM stats.stats_mysql_connection_pool where ConnERR=0 limit 10;
+-----------+---------------+----------+--------+----------+----------+--------+---------+-------------+---------+-------------------+-----------------+-----------------+------------+
| hostgroup | srv_host      | srv_port | status | ConnUsed | ConnFree | ConnOK | ConnERR | MaxConnUsed | Queries | Queries_GTID_sync | Bytes_data_sent | Bytes_data_recv | Latency_us |
+-----------+---------------+----------+--------+----------+----------+--------+---------+-------------+---------+-------------------+-----------------+-----------------+------------+
| 1000      | 192.110.103.41 | 3106     | ONLINE | 0        | 1        | 1      | 0       | 1           | 3       | 0                 | 75              | 28              | 156        |
| 1000      | 192.110.103.43 | 3106     | ONLINE | 0        | 1        | 2      | 0       | 1           | 5       | 0                 | 77              | 38              | 173        |
| 2000      | 192.110.103.41 | 3107     | ONLINE | 0        | 1        | 1      | 0       | 1           | 4       | 0                 | 59              | 28              | 169        |
+-----------+---------------+----------+--------+----------+----------+--------+---------+-------------+---------+-------------------+-----------------+-----------------+------------+
3 rows in set (0.01 sec)
複製代碼

stats_mysql_commands_counters:

stats_mysql_commands_counters是記錄各類類型的查詢精確的統計數據表。

admin> SELECT * FROM stats_mysql_commands_counters WHERE Total_cnt!=0;
+-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+--------+--------+---------+----------+
| Command           | 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 |
+-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+--------+--------+---------+----------+
| COMMIT            | 1075          | 7         | 0         | 7         | 0       | 0       | 0        | 0        | 0         | 0         | 0      | 0      | 0       | 0        |
| INSERT            | 7391          | 5         | 0         | 3         | 1       | 0       | 1        | 0        | 0         | 0         | 0      | 0      | 0       | 0        |
| SELECT            | 15419         | 40        | 22        | 11        | 3       | 3       | 1        | 0        | 0         | 0         | 0      | 0      | 0       | 0        |
| START_TRANSACTION | 3382          | 7         | 0         | 5         | 2       | 0       | 0        | 0        | 0         | 0         | 0      | 0      | 0       | 0        |
+-------------------+---------------+-----------+-----------+-----------+---------+---------+----------+----------+-----------+-----------+--------+--------+---------+----------+
4 rows in set (0.01 sec)
複製代碼

stats_mysql_processlist:

#相似mysql processlist。
show processlist;
select * from stats_mysql_processlist limit 1;
+----------+-----------+-----------+-------+---------------+----------+-----------+--------------+------------+-------------+----------+---------+---------+------+
| ThreadID | SessionID | user      | db    | cli_host      | cli_port | hostgroup | l_srv_host   | l_srv_port | srv_host    | srv_port | command | time_ms | info |
+----------+-----------+-----------+-------+---------------+----------+-----------+--------------+------------+-------------+----------+---------+---------+------+
| 0        | 1274067   | mgr01 | test | 192.75.217.107 | 21845    | 1000      | 192.110.154.98 | 46958      | 192.110.103.41 | 3106     | Sleep   | 2132    |      |
+----------+-----------+-----------+-------+---------------+----------+-----------+--------------+------------+-------------+----------+---------+---------+------+
1 row in set (0.00 sec)     
複製代碼

stats_mysql_query_digest:

stats_mysql_commands_counters表中提供了很是有用的信息。但能夠從stats_mysql_query_digest表獲取關於查詢的更多更詳細信息

SELECT * FROM stats_mysql_query_digest ORDER BY sum_time DESC limit 1;  
+-----------+------------+----------+----------------+--------------------+-----------------------+------------+------------+------------+----------+----------+----------+-------------------+---------------+
| hostgroup | schemaname | username | client_address | digest             | digest_text           | count_star | first_seen | last_seen  | sum_time | min_time | max_time | sum_rows_affected | sum_rows_sent |
+-----------+------------+----------+----------------+--------------------+-----------------------+------------+------------+------------+----------+----------+----------+-------------------+---------------+
| 1000      | test       | mgr01    |                | 0x67A9FB367B49CAB9 | select * from test.t1 | 180        | 1577933232 | 1577933377 | 61954    | 233      | 473      | 0                 | 900           |
+-----------+------------+----------+----------------+--------------------+-----------------------+------------+------------+------------+----------+----------+----------+-------------------+---------------+

SELECT hostgroup hg,username,client_address, sum_time, first_seen,count_star, digest_text FROM stats_mysql_query_digest ORDER BY sum_time DESC limit 6;
+------+----------+----------------+----------+------------+------------+-----------------------------------------+
| hg   | username | client_address | sum_time | first_seen | count_star | digest_text                             |
+------+----------+----------------+----------+------------+------------+-----------------------------------------+
| 1000 | mgr01    |                | 61954    | 1577933232 | 180        | select * from test.t1                   |
| 1000 | mgr01    |                | 44636    | 1577893404 | 192        | select @@server_id                      |
| 1000 | mgr01    |                | 12276    | 1577896355 | 10         | insert into test.t1(name) values(now()) |
| 2000 | mgr02    |                | 6838     | 1577896474 | 1          | select test.t1                          |
| 2000 | mgr02    |                | 6261     | 1577893409 | 19         | select @@server_id                      |
| 2000 | mgr02    |                | 3721     | 1577933528 | 12         | select * from test.t2                   |
+------+----------+----------------+----------+------------+------------+-----------------------------------------+
複製代碼

8.2 監控表信息

#監控表
admin> show tables from monitor;
+--------------------------------------+
| tables                               |
+--------------------------------------+
| mysql_server_aws_aurora_check_status |
| mysql_server_aws_aurora_failovers    |
| mysql_server_aws_aurora_log          |
| mysql_server_connect_log             |
| mysql_server_galera_log              |
| mysql_server_group_replication_log   |
| mysql_server_ping_log                |
| mysql_server_read_only_log           |
| mysql_server_replication_lag_log     |
+--------------------------------------+
9 rows in set (0.00 sec)
#
select * from mysql_server_ping_log limit 3;
+---------------+------+------------------+----------------------+------------+
| hostname      | port | time_start_us    | ping_success_time_us | ping_error |
+---------------+------+------------------+----------------------+------------+
| 192.110.103.41 | 3107 | 1577934435749261 | 166                  | NULL       |
| 192.110.103.42 | 3106 | 1577934435793805 | 170                  | NULL       |
| 192.110.103.42 | 3107 | 1577934435838352 | 197                  | NULL       |
+---------------+------+------------------+----------------------+------------+
select * from mysql_server_connect_log limit 3;
+---------------+------+------------------+-------------------------+---------------+
| hostname      | port | time_start_us    | connect_success_time_us | connect_error |
+---------------+------+------------------+-------------------------+---------------+
| 192.110.103.43 | 3106 | 1577934435331513 | 740                     | NULL          |
| 192.110.103.41 | 3107 | 1577934493460709 | 668                     | NULL          |
| 192.110.103.43 | 3106 | 1577934493851666 | 766                     | NULL          |
+---------------+------+------------------+-------------------------+---------------+
3 rows in set (0.00 sec)
select * from mysql_server_read_only_log limit 6; 
+---------------+------+------------------+-----------------+-----------+-------+
| hostname      | port | time_start_us    | success_time_us | read_only | error |
+---------------+------+------------------+-----------------+-----------+-------+
| 192.110.103.42 | 3107 | 1577934300775538 | 240             | 1         | NULL  |
| 192.110.103.42 | 3106 | 1577934300785584 | 229             | 1         | NULL  |
| 192.110.103.43 | 3107 | 1577934300795544 | 261             | 1         | NULL  |
| 192.110.103.41 | 3107 | 1577934300805554 | 263             | 0         | NULL  |
| 192.110.103.41 | 3106 | 1577934300815599 | 235             | 0         | NULL  |
| 192.110.103.43 | 3106 | 1577934300825618 | 249             | 1         | NULL  |
+---------------+------+------------------+-----------------+-----------+-------+
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
| hostname      | port | time_start_us    | success_time_us | viable_candidate | read_only | transactions_behind | error |
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
| 192.110.103.41 | 3106 | 1577934740449041 | 2530            | YES              | NO        | 0                   | NULL  |
| 192.110.103.41 | 3106 | 1577934745449110 | 2586            | YES              | NO        | 0                   | NULL  |
| 192.110.103.41 | 3106 | 1577934750449175 | 2437            | YES              | NO        | 0                   | NULL  |
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
3 rows in set (0.01 sec)
複製代碼

9. 問題處理

9.1 可讀但寫操做失敗

現象:

業務經過proxy來訪問DB,能夠讀操做,可是寫操做失敗。出錯信息:Lost connection to MySQL server during query,此錯誤信息明顯不一樣與表不存在的錯誤。

mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "insert into test.t1(name) values(now());select @@server_id; "   
ERROR 2013 (HY000) at line 1: Lost connection to MySQL server during query

#表不存在的現象
mysql -umgr02 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select * from test.t1 "
ERROR 1146 (42S02) at line 1: Table 'test.t1' doesn't exist 複製代碼

檢查:

#檢查日誌
tail -f /var/lib/proxysql/proxysql.log    
2020-01-02 00:21:52 MySQL_Session.cpp:4204:handler(): [WARNING] Error during query on (2000,192.110.103.43,3107): 1290, The MySQL server is running with the --read-only option so it cannot execute this statement

#proxysql
admin> select * from mysql_servers;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+

6 rows in set (0.00 sec)| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment  |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 1000         | 192.110.103.41 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-01 |
| 1000         | 192.110.103.42 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-02 |
| 1000         | 192.110.103.43 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-03 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
#單主模式
mysql -h 192.110.103.43 -P 3106 test -e "select @@group_replication_single_primary_mode;"
+-----------------------------------------+
| @@group_replication_single_primary_mode |
+-----------------------------------------+
|                                       1 |
+-----------------------------------------+
mysql -h 192.110.103.43 -P 3106 test -e " show global variables like '%only%';" 
+-------------------------------+-------+
| Variable_name                 | Value |
+-------------------------------+-------+
| innodb_optimize_fulltext_only | OFF   |
| innodb_read_only              | OFF   |
| read_only                     | ON    |
| super_read_only               | ON    |
| transaction_read_only         | OFF   |
| tx_read_only                  | OFF   |
+-------------------------------+-------+
複製代碼

緣由:

由mysql_servers表能夠看到1000組中同時存在多個DB實例,而我們是MGR單主模式。故當寫操做路由到只讀的實例時,將會出錯。即報出的Lost connection to MySQL server during query。

處理:

我們設置mysql_replication_hostgroups信息,讓mgr01的從庫變爲讀組1002組,將可解決此誤寫只讀庫的問題。

select * from runtime_mysql_servers;
select * from runtime_replication_hostgroups;
#增長讀寫組信息,讓proxy依read_only對DB實例分讀寫組.
insert into mysql_replication_hostgroups values(1000,1002,'read_only','mgr01'); 
LOAD MYSQL SERVERS TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
#生效讓mgr01的從庫,變爲讀組1002組,將解決此問題。
admin> select * from runtime_mysql_servers 
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment  |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 1000         | 192.110.103.41 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-01 |
| 1002         | 192.110.103.43 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-03 |
| 1002         | 192.110.103.42 | 3106 | 0         | ONLINE | 1      | 0           | 2000            | 0                   | 0       | 0              | MGR01-02 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+

#測試是否ok
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "insert into test.t1(name) values(now());select @@server_id; "   
+-------------+
| @@server_id |
+-------------+
|   103413106 |
+-------------+
複製代碼

參考:


陶老師運維筆記
)

ProxySQL
相關文章
相關標籤/搜索