MySQL中间件 ProxySQL代理MGR
文章来源: 陶老师运维笔记- 微信公众号
1. 背景介绍
ProxySQL介绍:
- Doc : https://github.com/sysown/proxysql/wiki#getting-started
- Howto : https://github.com/sysown/proxysql/wiki/ProxySQL-Configuration
ProxySQL 是一个较轻量但功能强大的MySQL中间件。可以很好的支持 Master Slave, MGR, PXC等MySQL架构,并提供连接池、读写分离、日志记录等功能。
MySQL MGR 介绍:
- MySQL5.7 MGR介绍及安装
MySQL Group Replication(简称MGR)是由多个实例节点共同组成一个数据库集群,系统提交事务必须经过半数以上节点同意方可提交,在集群中每个节点上都维护一个数据库状态机,保证节点间事务的一致性.
MySQL组复制分单主模式和多主模式,MGR复制技术仅解决了数据一致性问题。当Master 宕机,应用系统可能仍需要修改数据库主库连接地址,才能保证服务的可用性:(。
为解决此问题,咱们可以在MRG上层增加一Proxy代理层,例如本文介绍的ProxySQL。
2. 测试环境
2.1 环境规划
角色 | 版本 | IP | port | server-id |
---|---|---|---|---|
Proxy-1 | 2.0.8 | 192.110.154.98 | 6032/6033 | - |
DB-1 | MySQL5.7.23 | 192.110.103.41 | 3106 | 103413106 |
DB-2 | MySQL5.7.23 | 192.110.103.42 | 3106 | 103423106 |
DB-3 | MySQL5.7.23 | 192.110.103.43 | 3106 | 103433106 |
MGR信息: MySQL机器IP,192.110.103.41/42/43,Port:3106。MGR为单主模式,DB-1为Master。
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)
192.110.103.41 : test > show global variables like '%group_replication_single_primary_mode%';
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| group_replication_single_primary_mode | ON |
+---------------------------------------+-------+
1 row in set (0.00 sec)
#
SELECT ta.* ,tb.MEMBER_HOST,tb.MEMBER_PORT,tb.MEMBER_STATE FROM performance_schema.global_status ta,performance_schema.replication_group_members tb
WHERE ta.VARIABLE_NAME='group_replication_primary_member' and ta.VARIABLE_VALUE=tb.MEMBER_ID;
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
| VARIABLE_NAME | VARIABLE_VALUE | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
| group_replication_primary_member | 509810ee-f3d7-11e9-a7d5-a0369fac2de4 | 192.110.103.41 | 3106 | ONLINE |
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
#
3. ProxSQL安装
- ProxySQL官方网站: https://proxysql.com/
- MySQL中间件ProxySQL2.x安装及测试
下载
$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
启停/状态
#查看版本
$proxysql --version
#存储目录
#ls /var/lib/proxysql/
#启动/停止
$service proxysql start
$service proxysql stop
$service proxysql status # 查看proxysql状态
ProxySQL is running (20761).
测试
$proxysql --version
mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '
admin> show databases;
4. 配置主机
4.1 连接配置接口
成功启动后,就使用原始账号admin/admin可以登录proxy管理接口6032。
mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt='Admin> '
Admin> show databases;
+-----+---------------+-------------------------------------+
| seq | name | file |
+-----+---------------+-------------------------------------+
| 0 | main | |
| 2 | disk | /var/lib/proxysql/proxysql.db |
| 3 | stats | |
| 4 | monitor | |
| 5 | stats_history | /var/lib/proxysql/proxysql_stats.db |
+-----+---------------+-------------------------------------+
5 rows in set (0.00 sec)
库说明:
- main库是ProxySQL最主要的库, 是内存数据库,修改配置时必须将其持久化到disk永久保存。
- disk库是磁盘数据库,该数据库结构和内存数据库完全一致。
- stats库是统计信息库。这个库中的数据一般是在检索其内数据时临时填充的,它保存在内存中。
- monitor库是监控后端MySQL节点相关的库,该库中只有几个log表存监控信息。
- stats_history库是1.4.4版新增的库,用于存放历史统计数据。
4.2 配置主机
mysql_server表中增加MGR01组的机器,192.110.103.41:3106-192.110.103.43:3106。
#
select * from mysql_servers;
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(100,2000,'MGR01-01','192.110.103.41',3106);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(100,2000,'MGR01-02','192.110.103.42',3106);
insert into mysql_servers(hostgroup_id,max_connections,comment,hostname,port) values(100,2000,'MGR01-03','192.110.103.43',3106);
#select hostgroup_id,hostname,port,status,weight from mysql_servers;
select * from mysql_servers where port=3106;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| hostgroup_id | hostname | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 100 | 192.110.103.41 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-01 |
| 100 | 192.110.103.42 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-02 |
| 100 | 192.110.103.43 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-03 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
配置读写分组:
对ProxySQL中的节点分组:writer_hostgroup、reader_hostgroup。#1.4x版本/2.x版本是有区别的
加载生效后,Monitor模块就会开始监控mysql_replication_hostgroups表check_type,如read_only/super_read_only等值,当监控到read_only/super_read_only值后,就会按照read_only/super_read_only的值将某些节点自动移动到读/写组。
#insert into mysql_replication_hostgroups values(100,102,'-'); #1.4x版本
insert into mysql_replication_hostgroups values(100,102,'read_only','-'); #2.x版本
#将刚才mysql_replication_hostgroups表的修改加载到RUNTIME生效。
load mysql servers to runtime;
save mysql servers to disk;
#
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 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 100 | 192.110.103.41 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-01 |
| 102 | 192.110.103.42 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-02 |
| 102 | 192.110.103.43 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-03 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
3 rows in set (0.00 sec)
5. 监控后端节点
ProxySQL有两种账号:区分admin,stat管理接口的用户名和mysql_users中的用户名。
- admin管理接口的用户: 是连接到管理接口(默认端口6032)上用来管理、配置ProxySQL的。
- mysql_users表中的用户: 是应用程序连接ProxySQL(默认端口6033),以及ProxySQL连接后端MySQL Servers使用的用户。它的作用是发送、路由SQL语句,类似于MySQL Server的3306端口。所以,这个表中的用户必须已经在后端MySQL Server上存在且授权了!
ProxySQL需要监控后端节点的状态权限。因为ProxySQL需要通过每个节点的read_only值来自动调整它们是属于读组还是写组。
DB上增加监控账号:
在DB Master上创建ProxySQL监控用户。注意的是, ProxySQL代理MGR组复制时,是从MGR的系统视图sys.gr_member_routing_candidate_status中获取监控指标,所以授予监控用户对该视图的查询权限,因为无需从show slave status中获取Seconds_Behind_Master,所以无需replication client权限。
#MySQL Master
create user monitor@'%' identified by 'P@ssword1!';
grant select on sys.* to monitor@'%';
#可不授replication client权限.
#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%';
#生效
load mysql variables to runtime;
save mysql variables to disk;
检查是否生效:
ProxySQL监控模块的指标都保存在monitor库的log表中。
#ProxySQL监控模块的指标都保存在monitor库的log表中。
mysql -uadmin -padmin -P6032 -h127.0.0.1 --prompt 'admin> '
admin> select * from mysql_server_connect_log order by time_start_us desc limit 6;
+---------------+------+------------------+-------------------------+---------------+
| hostname | port | time_start_us | connect_success_time_us | connect_error |
+---------------+------+------------------+-------------------------+---------------+
| 192.110.103.41 | 3106 | 1577096966015232 | 613 | NULL |
| 192.110.103.43 | 3106 | 1577096965257056 | 610 | NULL |
| 192.110.103.42 | 3106 | 1577096964498874 | 643 | NULL |
| 192.110.103.41 | 3106 | 1577096906082375 | 785 | NULL |
| 192.110.103.42 | 3106 | 1577096905290598 | 598 | NULL |
| 192.110.103.43 | 3106 | 1577096904498801 | 800 | NULL |
+---------------+------+------------------+-------------------------+---------------+
6 rows in set (0.00 sec)
select * from mysql_server_ping_log order by time_start_us desc limit 30;
+---------------+------+------------------+----------------------+------------+
| hostname | port | time_start_us | ping_success_time_us | ping_error |
+---------------+------+------------------+----------------------+------------+
| 192.110.103.43 | 3106 | 1577096914589065 | 195 | NULL |
| 192.110.103.42 | 3106 | 1577096914483012 | 187 | NULL |
| 192.110.103.41 | 3106 | 1577096914376942 | 193 | NULL |
| 192.110.103.41 | 3106 | 1577096904578993 | 192 | NULL |
| 192.110.103.43 | 3106 | 1577096904477957 | 182 | NULL |
| 192.110.103.42 | 3106 | 1577096904376893 | 183 | NULL |
+---------------+------+------------------+----------------------+------------+
6. 创建视图sys.gr_member_routing_candidate_status(2.0.x可略)
- proxysql 2.0.x 可略过此步骤,但1.4.12等旧版本需要。
- proxysql1.4.x尽管已原生支持MGR,但仍然需要在MGR节点中创建一张额外的系统视图sys.gr_member_routing_candidate_status为ProxySQL提供监控指标。
若proxysql为1.4.x则需要在DB master上执行,如下命令:
#wget https://files.cnblogs.com/files/f-ck-need-u/addition_to_sys.zip
USE sys;
DELIMITER $$
CREATE FUNCTION IFZERO(a INT, b INT)
RETURNS INT
DETERMINISTIC
RETURN IF(a = 0, b, a)$$
CREATE FUNCTION LOCATE2(needle TEXT(10000), haystack TEXT(10000), offset INT)
RETURNS INT
DETERMINISTIC
RETURN IFZERO(LOCATE(needle, haystack, offset), LENGTH(haystack) + 1)$$
CREATE FUNCTION GTID_NORMALIZE(g TEXT(10000))
RETURNS TEXT(10000)
DETERMINISTIC
RETURN GTID_SUBTRACT(g, '')$$
CREATE FUNCTION GTID_COUNT(gtid_set TEXT(10000))
RETURNS INT
DETERMINISTIC
BEGIN
DECLARE result BIGINT DEFAULT 0;
DECLARE colon_pos INT;
DECLARE next_dash_pos INT;
DECLARE next_colon_pos INT;
DECLARE next_comma_pos INT;
SET gtid_set = GTID_NORMALIZE(gtid_set);
SET colon_pos = LOCATE2(':', gtid_set, 1);
WHILE colon_pos != LENGTH(gtid_set) + 1 DO
SET next_dash_pos = LOCATE2('-', gtid_set, colon_pos + 1);
SET next_colon_pos = LOCATE2(':', gtid_set, colon_pos + 1);
SET next_comma_pos = LOCATE2(',', gtid_set, colon_pos + 1);
IF next_dash_pos < next_colon_pos AND next_dash_pos < next_comma_pos THEN
SET result = result +
SUBSTR(gtid_set, next_dash_pos + 1,
LEAST(next_colon_pos, next_comma_pos) - (next_dash_pos + 1)) -
SUBSTR(gtid_set, colon_pos + 1, next_dash_pos - (colon_pos + 1)) + 1;
ELSE
SET result = result + 1;
END IF;
SET colon_pos = next_colon_pos;
END WHILE;
RETURN result;
END$$
CREATE FUNCTION gr_applier_queue_length()
RETURNS INT
DETERMINISTIC
BEGIN
RETURN (SELECT sys.gtid_count( GTID_SUBTRACT( (SELECT
Received_transaction_set FROM performance_schema.replication_connection_status
WHERE Channel_name = 'group_replication_applier' ), (SELECT
@@global.GTID_EXECUTED) )));
END$$
CREATE FUNCTION gr_member_in_primary_partition()
RETURNS VARCHAR(3)
DETERMINISTIC
BEGIN
RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((SELECT COUNT(*) FROM
performance_schema.replication_group_members WHERE MEMBER_STATE != 'ONLINE') >=
((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2) = 0),
'YES', 'NO' ) FROM performance_schema.replication_group_members JOIN
performance_schema.replication_group_member_stats USING(member_id));
END$$
CREATE VIEW gr_member_routing_candidate_status AS SELECT
sys.gr_member_in_primary_partition() as viable_candidate,
IF( (SELECT (SELECT GROUP_CONCAT(variable_value) FROM
performance_schema.global_variables WHERE variable_name IN ('read_only',
'super_read_only')) != 'OFF,OFF'), 'YES', 'NO') as read_only,
sys.gr_applier_queue_length() as transactions_behind, Count_Transactions_in_queue as 'transactions_to_cert' from performance_schema.replication_group_member_stats;$$
DELIMITER ;
查看该视图:
192.110.103.41 :sys > select * from sys.gr_member_routing_candidate_status;
+------------------+-----------+---------------------+----------------------+
| viable_candidate | read_only | transactions_behind | transactions_to_cert |
+------------------+-----------+---------------------+----------------------+
| YES | NO | 0 | 0 |
+------------------+-----------+---------------------+----------------------+
1 row in set (0.03 sec)
7. 录入MGR hostgroups信息
- https://github.com/sysown/proxysql/wiki/Main-(runtime)#mysql_group_replication_hostgroups
7.1 mysql_group_replication_hostgroups表
select * from mysql_group_replication_hostgroups;
-- 表结构
show create table mysql_group_replication_hostgroups\G
*************************** 1. row ***************************
table: mysql_group_replication_hostgroups
Create Table: CREATE TABLE mysql_group_replication_hostgroups (
writer_hostgroup INT CHECK (writer_hostgroup>=0) NOT NULL PRIMARY KEY,
backup_writer_hostgroup INT CHECK (backup_writer_hostgroup>=0 AND backup_writer_hostgroup<>writer_hostgroup) NOT NULL,
reader_hostgroup INT NOT NULL CHECK (reader_hostgroup<>writer_hostgroup AND backup_writer_hostgroup<>reader_hostgroup AND reader_hostgroup>0),
offline_hostgroup INT NOT NULL CHECK (offline_hostgroup<>writer_hostgroup AND offline_hostgroup<>reader_hostgroup AND backup_writer_hostgroup<>offline_hostgroup AND offline_hostgroup>=0),
active INT CHECK (active IN (0,1)) NOT NULL DEFAULT 1,
max_writers INT NOT NULL CHECK (max_writers >= 0) DEFAULT 1,
writer_is_also_reader INT CHECK (writer_is_also_reader IN (0,1,2)) NOT NULL DEFAULT 0,
max_transactions_behind INT CHECK (max_transactions_behind>=0) NOT NULL DEFAULT 0,
comment VARCHAR,
UNIQUE (reader_hostgroup),
UNIQUE (offline_hostgroup),
UNIQUE (backup_writer_hostgroup))
1 row in set (0.00 sec)
各字段的意义如下:
- writer_hostgroup:默认的写组。后端read_only=0的节点会自动分配到这个组中。
- backup_writer_hostgroup:为备份节点组。超出max_writers数量的但允许写的节点都会放进备份组backup_writer_hostgroup中。
- reader_hostgroup:负责读的组。读请求都会路由到该主机组中的节点,后端read_only=1的节点会自动分配到这个组中。
- offline_hostgroup:当ProxySQL监控并决定了某节点为OFFLINE后,会将其放进组offline_hostgroup中。
- active:当启用后,ProxySQL会监控该主机组,并在不同组之间合理地移动节点。
- max_writers:该字段的值决定writer_hostgroup中最大允许的节点数。
- writer_is_also_reader:决定一个节点升级为写节点(放进writer_hostgroup)后是否仍然保留在reader_hostgroup组中提供读服务。
- max_transactions_behind: 当某节点延后于写节点时,为了防止读取到过期数据,ProxySQL可能会自动避开该节点。
- comment:该字段用于说明、注释,可随便定义。
注意:
- ProxySQL代理每一个后端MGR集群时,都必须为这个MGR定义读组、写组、备写组、离线组,且这四个组的值各不相同、不允许NULL、具有唯一性。
- ProxySQL代理多主模型的MGR时,必须设置writer_is_also_reader=1。
7.2 录入MGR组信息
如果想让ProxySQL来自动调整节点所属读、写组,需要开启read_only监控,并在mysql_group_replication_hostgroups表中插入一条记录。
插入数据:
#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(100,101,102,103,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(200,201,202,203,1,1,0,10,'cluster-mgr02');
#select * from runtime_mysql_replication_hostgroups;
上述配置中,本例中writer_is_also_reader设置为false,则master只负责写操作。
配置生效:
load mysql servers to runtime;
save mysql servers to disk;
查看录入结果
select * from mysql_group_replication_hostgroups;
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
| writer_hostgroup | backup_writer_hostgroup | reader_hostgroup | offline_hostgroup | active | max_writers | writer_is_also_reader | max_transactions_behind | comment |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
| 100 | 101 | 102 | 103 | 1 | 1 | 1 | 10 | MGR01 |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
查看实时服务器状态
select hostgroup_id, hostname, port,status from runtime_mysql_servers;
+--------------+---------------+------+--------+
| hostgroup_id | hostname | port | status |
+--------------+---------------+------+--------+
| 100 | 192.110.103.41 | 3106 | ONLINE |
| 100 | 192.110.103.43 | 3106 | ONLINE |
| 100 | 192.110.103.42 | 3106 | ONLINE |
+--------------+---------------+------+--------+
查看检测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 6;
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
| 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 |
| 192.110.103.43 | 3106 | 1577540018301516 | 2452 | YES | YES | 0 | NULL |
| 192.110.103.42 | 3106 | 1577540018301192 | 2824 | YES | YES | 0 | NULL |
| 192.110.103.41 | 3106 | 1577540018300907 | 2610 | YES | NO | 0 | NULL |
+---------------+------+------------------+-----------------+------------------+-----------+---------------------+-------+
6 rows in set (0.00 sec)
8. 配置mysql_users
在DB Master节点上执行:
#MySQL Master, 可依用户名来区分多组DB,来实现路由
grant select,insert,update,delete on *.* to 'mgr01'@'%' identified by 'P@ssword1!';
grant all on *.* to mgr01_root@'%' identified by 'P@ssword1!';
#proxy v2.0.8
delete from mysql_users;
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr01','P@ssword1!',100,1);
insert into mysql_users(username,password,default_hostgroup,transaction_persistent) values('mgr01_root','P@ssword1!',100,1);
#proxy v1.4.x
insert into mysql_users(username,password,default_hostgroup,transaction_persistent,comment) values('mgr01','P@ssword1!',100,1,'MRG01');
insert into mysql_users(username,password,default_hostgroup,transaction_persistent,comment) values('mgr01_root','P@ssword1!',100,1,'MGR01');
#
#select * from mysql_servers;
#select * from mysql_group_replication_hostgroups;
admin> select username,password,active,default_hostgroup,max_connections,comment from mysql_users;
+------------+------------+--------+-------------------+-----------------+---------+
| username | password | active | default_hostgroup | max_connections | comment |
+------------+------------+--------+-------------------+-----------------+---------+
| mgr01 | P@ssword1! | 1 | 100 | 10000 | |
| mgr01_root | P@ssword1! | 1 | 100 | 10000 | |
+------------+------------+--------+-------------------+-----------------+---------+
2 rows in set (0.00 sec)
#
load mysql users to runtime;
save mysql users to disk;
说明:
- 注意hostgroup要和mysql_servers中的组相一致,comment做为备注为MGR01机群。
- 建议为不同的DB组使用不同的用户名,如mgr01,mgr02,这样一个proxy可方便路由多组DB。
9. 读写分离
测试是否按预期进行读写分离。目前DB-1,192.110.103.41机器为主,read_only为off。
9.1 读写分离配置
ProxySQL的路由规则非常灵活,可配置读/写分离,也可配置从各项指标中找出压力大、执行频繁的语句单独写规则、做缓存等等。
- 查询规则表有:mysql_query_rules和mysql_query_rules_fast_routing,后者是前者的扩展表。
- 读写分离可配置mysql_query_rules,但是若是代理了多组DB则不方便配置mysql_query_rules(可不配置)。
select * from mysql_query_rules;
insert into mysql_query_rules(rule_id,active,match_digest,destination_hostgroup,apply)
VALUES (1,1,'^SELECT.*FOR UPDATE$',100,1), (2,1,'^SELECT',102,1);
load mysql query rules to runtime;
save mysql query rules to disk;
#查看语句路由状态:
select hostgroup,digest_text from stats_mysql_query_digest;
9.2 测试读写分离
当前DB情况:
192.110.103.41 : test > show global variables like '%group_replication_single_primary_mode%';
+---------------------------------------+-------+
| Variable_name | Value |
+---------------------------------------+-------+
| group_replication_single_primary_mode | ON |
+---------------------------------------+-------+
1 row in set (0.00 sec)
#
SELECT ta.* ,tb.MEMBER_HOST,tb.MEMBER_PORT,tb.MEMBER_STATE FROM performance_schema.global_status ta,performance_schema.replication_group_members tb
WHERE ta.VARIABLE_NAME='group_replication_primary_member' and ta.VARIABLE_VALUE=tb.MEMBER_ID;
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
| VARIABLE_NAME | VARIABLE_VALUE | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
| group_replication_primary_member | 509810ee-f3d7-11e9-a7d5-a0369fac2de4 | 192.110.103.41 | 3106 | ONLINE |
+----------------------------------+--------------------------------------+---------------+-------------+--------------+
#41 DB-1只读为OFF, 42/43的DB为ON。
mysql -h 192.110.103.42 -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 |
+-------------------------------+-------+
DB创建测试表:
#在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 ;
当前proxy配置情况:
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 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 100 | 192.110.103.41 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-01 |
| 102 | 192.110.103.42 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-02 |
| 102 | 192.110.103.43 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-03 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
3 rows in set (0.00 sec)
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 |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
| 100 | 101 | 102 | 103 | 1 | 1 | 0 | 10 | MGR01 |
+------------------+-------------------------+------------------+-------------------+--------+-------------+-----------------------+-------------------------+---------+
1 row in set (0.00 sec)
#
select * from runtime_mysql_replication_hostgroups;
+------------------+------------------+------------+---------+
| writer_hostgroup | reader_hostgroup | check_type | comment |
+------------------+------------------+------------+---------+
| 100 | 102 | read_only | - |
+------------------+------------------+------------+---------+
1 row in set (0.00 sec)
#
select * from mysql_server_group_replication_log limit 6;
#
select username,password,active,default_hostgroup,transaction_persistent,backend,frontend,comment from runtime_mysql_users;
+------------+-------------------------------------------+--------+-------------------+------------------------+---------+----------+---------+
| username | password | active | default_hostgroup | transaction_persistent | backend | frontend | comment |
+------------+-------------------------------------------+--------+-------------------+------------------------+---------+----------+---------+
| mgr01_root | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 | 1 | 100 | 1 | 0 | 1 | |
| mgr01 | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 | 1 | 100 | 1 | 0 | 1 | |
| mgr01_root | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 | 1 | 100 | 1 | 1 | 0 | |
| mgr01 | *50572A5FABC7DA9CEE5EB5977EDDE59E38967422 | 1 | 100 | 1 | 1 | 0 | |
+------------+-------------------------------------------+--------+-------------------+------------------------+---------+----------+---------+
4 rows in set (0.00 sec)
测试读/写:
#测试读
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select @@server_id; "
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "select * from test.t1; select @@server_id; "
#测试写
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 -e 'start transaction;select @@server_id;commit;'
+-------------+
| @@server_id |
+-------------+
| 10341 |
+-------------+
mysql -umgr01 -pP@ssword1! -P6033 -h127.0.0.1 test -e "insert into test.t1(name) values(now());select @@server_id; "
select hostgroup,digest_text from stats_mysql_query_digest ORDER BY sum_time DESC limit 10;
proxysql_admin> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest order by last_seen desc limit 10;
+-----------+--------------------+----------+-----------------------------------------+
| hostgroup | schemaname | username | digest_text |
+-----------+--------------------+----------+-----------------------------------------+
| 100 | test | mgr01 | insert into test.t1(name) values(now()) |
| 100 | test | mgr01 | select @@server_id |
| 100 | test | mgr01 | select @@version_comment limit ? |
| 100 | information_schema | mgr01 | select @@server_id |
| 100 | information_schema | mgr01 | select @@version_comment limit ? |
| 100 | information_schema | mgr01 | commit |
| 100 | information_schema | mgr01 | start transaction |
| 100 | test | mgr01 | select * from test.t1 |
| 100 | test | mgr01 | insert into test.t1(name) values(?) |
+-----------+--------------------+----------+-----------------------------------------+
10. MGR故障转移
将MGR的某个节点停掉,咱们把DB1 master停掉,测试业务影响。
停止Master DB:
#当前情况:
SELECT * FROM performance_schema.replication_group_members;
select * from performance_schema.replication_group_member_stats;
192.110.103.41 : test > stop group_replication;
读写DB影响:
可以发现proxy hostgroup会自动切换,业务通过proxy写操作不会受影响。
##
hostgroup 100信息将会变化:由192.110.103.41变为42了。
proxysql_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 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
| 100 | 192.110.103.42 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-02 |
| 102 | 192.110.103.41 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-01 |
| 102 | 192.110.103.42 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-02 |
| 102 | 192.110.103.43 | 3106 | 0 | ONLINE | 1 | 0 | 2000 | 0 | 0 | 0 | MGR01-03 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+----------+
4 rows in set (0.00 sec)
##写已变成了新的机器42。业务仍可正常写入数据。
mysql -uroot -pP@ssword1! -P6033 -h127.0.0.1 test -e "insert into test.t1(name) values('a113');select @@server_id; " #自增id不会链续。
+-------------+
| @@server_id |
+-------------+
| 10342 |
+-------------+
#
参考:
- 官方网站:https://proxysql.com/
- https://github.com/sysown/proxysql/wiki#getting-started
- https://github.com/sysown/proxysql/wiki
- https://github.com/sysown/proxysql/wiki/ProxySQL-Configuration
- 中文文档 https://github.com/malongshuai/proxysql/wiki
- 陶老师运维笔记- ProxySQL2.x安装及测试
- 骏马金龙 ProxySQL