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
相关文章
相关标签/搜索