MySQL 8.x配置MGR高可用+ProxySQL读写分离(三):配置ProxySQL主从分组信息
#作者:stackofumbrella
文章目录
- 配置ProxySQL主从分组信息
- ProxySQL配置监控MySQL节点
- ProxySQL配置对外访问账号
- 配置读写分离策略
配置ProxySQL主从分组信息
用到这个表mysql_replication_hostgroup,表结构信息如下
mysql> show create table mysql_replication_hostgroups\G;
创建组
writer_hostgroup和reader_hostgroup写组和读组都要大于0且不能相同
insert into mysql_replication_hostgroups ( writer_hostgroup, reader_hostgroup, comment) values (10,20,'proxy');
load mysql servers to runtime;
save mysql servers to disk;
查看是否写入配置
select * from main.mysql_replication_hostgroups;
select * from main.runtime_mysql_replication_hostgroups;
select * from runtime_mysql_replication_hostgroups;
select * from mysql_replication_hostgroups;
ProxySQL会根据server的read _only的取值将服务器进行分组。read_only=0的server,master被分到编号为10的写组,read_only=1的server,slave则被分到编号20的读组。
添加主从服务器节点
查看main.mysql_servers这个表
show create table main.mysql_servers\G;
执行配置SQL语句
insert into main.mysql_servers(hostgroup_id,hostname,port) values (10,'192.168.1.46',3306);
insert into main.mysql_servers(hostgroup_id,hostname,port) values (20,'192.168.1.47',3306);
insert into main.mysql_servers(hostgroup_id,hostname,port) values (20,'192.168.1.48',3306);
load mysql servers to runtime;
save mysql servers to disk;
查看节点状态
select * from main.mysql_servers;
表字段的解释
hostgroup_id:ProxySQL通过hostgroup的形式组织后端db实例,一个hostgroup代表同属于一个角色。表的主键是(hostgroup_id, hostname, port),以hostname:port在多个hostgroup中存在。一个hostgroup可以有多个实例,即是多个从库,可能通过weight分配权重。hostgroup_id 0是一个特殊的hostgroup,路由查询的时候,没有匹配到规则默认选择hostgroup 0。
status:
- ONLINE:当前后端实例状态正常。
- SHUNNED:临时被剔除,可能因为后端too many connection error,或者超过了max_replication_lag。
- OFFLINE_SOFT:软离线状态,不再接受新的连接,但已建立的连接会等待活跃事务完成。
- OFFLINE_HARD:硬离线状态,不再接受新的连接,已建立的连接或被强制中断,当后端实例宕机或网络不可达会出现。
- max_connections:允许连接到该后端实例的最大连接数,不要大于MySQL的
max_connections。如果后端实例hostname:port在多个hostgroup里,以较大者为准,而不是各自独立允许的最大连接数。 - max_replication_lag:允许的最大延迟,主库不受影响,默认为0,如果>0,monitor模块监控主从延迟大于阈值时,会临时把它的状态变更为SHUNNED。
- max_latency_ms:mysql_ping响应时间,大于这个阈值会把它从连接池剔除,即使是ONLINE。
- comment:备注,不建设为空。
ProxySQL配置监控MySQL节点
在ProxySQL节点上配置监控账号
- 第一种修改方法,修改变量的方式
set mysql-monitor_username=‘monitor’;
set mysql-monitor_password=‘123456’; - 第二种修改方法,修改main库下的表
use main;
UPDATE global_variables SET variable_value=‘monitor’ WHERE variable_name=‘mysql-monitor_username’;
UPDATE global_variables SET variable_value=‘123456’ WHERE variable_name=‘mysql-monitor_password’; - 修改后,保存到runtime和disk
load mysql variables to runtime;
save mysql variables to disk;
查看connect监控信息
ProxySQL监控模块的指标都保存在monitor库的log表中。以下是监控的状态信息,对于connect指标的监控 ,在前面可能会有很多connect_error,这是因为没有配置监控信息时的错误,配置后如果connect_error的结果为NULL则表示正常。
select * from monitor.mysql_server_connect_log;
查看心跳信息的监控
select * from monitor.mysql_server_ping_log limit 10;
查看read_only的监控
select * from monitor.mysql_server_read_only_log limit 10;
说明:monitor库监控后端read_only的值,就会将某些节点自动移动到读写组,同时所有的监控状态都在monitor库下的global_variables变量。
ProxySQL配置对外访问账号
在proxysql节点上main库的mysql_users配置proxysql账户,密码是123456,表结构信息如下
show create table main.mysql_users\G;
添加proxysql用户
insert into main.mysql_users (username,password,default_hostgroup) values (‘proxysql’,‘123456’,10);
load mysql users to runtime;
save mysql users to disk;
select * from main.mysql_users\G
说明
mysql_users表有不少字段,最主要的三个字段是username,password,default_hostgroup
username:前端链接ProxySQL ,以及ProxySQL将SQL语句路由给MySQL所使用的用户名
password:用户名对应的密码,可以是明文密码,也可以是hash密码。如果想使用hash密码,可以先在某个MySQL节点上执行select password(PASSWORD),然后将加密结果添加到该字段
active:该用户是否生效,active=0的用户将在数据库中被跟踪,但不会加载到内存中的数据结构中
default_hostgroup:该用户名默认的路由目标。例如,指定root用户的该字段值为10时,则使用proxysql用户发送的SQL语句,默认情况下将路由到hostgroup_id=10组中的某个节点,这里配置的hostgroup_id=10组中只有master一个节点
default_schema:这个用户连接时没有指定schema时,默认使用的schema,默认为NULL,实际上受变量mysql-default_schema的影响,默认为information_schema
transaction_persistent: 如果设置为1,连接上ProxySQL的会话后,如果在一个hostgroup上开启了事务,那么后续的sql都继续维持在这个hostgroup上,不论是否会匹配上其它路由规则,直到事务结束
frontend:如果设置为1,则用户名、密码对ProxySQL进行身份验证
backend:如果设置为1,则用户名、密码根据任何主机组向mysql服务器进行身份验证
测试路由
在ProxySQL节点上访问服务端口登录ProxySQL,并创建一个测试库,看是否路由到hostgroup_id=10的写组中的master
$ mysql -uproxysql -p -P 6033 -h 192.168.1.51
登录到master和其中一个slave查看是否创建成功
配置读写分离策略
配置读写分离,就是配置ProxySQL路由规则,ProxySQL的路由规则非常灵活,可以基于用户,基于schema,以及单个sql语句实现路由规则定制。
注意:实际情况配置路由规则,不应该根据所谓的读、写操作来进行分离,而是从收集(慢日志)的各项指标找出压力大,执行频繁的语句单独写规则,做缓存等。比如先测试几个核心sql语句,分析性能提升的百分比,在逐渐慢慢完善路由规则。 生产中使用读写分离建议基于hash code值做读写分离,不要建太多的规则。
和查询规则有关的表有两个mysql_query_rules和mysql_query_rules_fast_routing。表mysql_query_rules_fast_routing是mysql_query_rules的扩展,并在以后评估快速路由策略和属性(仅在ProxySQL 1.4.7+中可用)。
表mysql_query_rules的字段含义:
- rule_id:表主键,自增,规则处理是以rule_id为顺序进行
- active:是否启用这个规则,1表示启用,0表示禁用
- username:过滤匹配用户名的条件,如果是非空值,则仅当连接使用正确的用户名时,查询才匹配
- schemaname:匹配schemaname的过滤条件,如果是非空值,则仅当连接schemaname用作默认模式时,查询才匹配
- flagIN,flagOUT,apply:用来定义路由链chains of rules,首先会检查flagIN=0的规则,以rule_id的顺序;如果没有匹配上,则走这个用户的default_hostgroup。当匹配一条规则后,会检查flagOUT。如果不为NULL,并且flagIN!=flagOUT,则进入以flagIN为上一个flagOUT值的新规则链。如果不为NULL,并且flagIN=flagOUT,则应用这条规则。如果为NULL,或者apply=1,则结束,应用这条规则。如果最终没有匹配到,则找到这个用户的default_hostgroup
- client_addr:匹配客户端来源IP
- proxy_addr,proxy_port:匹配本地proxysql的ip、端口
- digest:精确匹配的查询
- match_digest:正则匹配查询。query,digest是指对查询去掉具体值后进行”模糊化“后的查询,类似pt-query-digest的效果
- match_pattern:字段就是代表设置规则
- negate_match_pattern:反向匹配,相当于对match_digest/match_pattern的匹配取反
- re_modifiers:修改正则匹配的参数,比如默认忽略大小写CASELESS、禁用GLOBAL
下面是匹配后的行为:
- replace_pattern:查询重写,默认为空。
- destination_hostgroup:路由查询到这个hostgroup,当然如果用户显式start transaction且transaction_persistent=1,那么即使匹配到了,也依然按照事务里第一条sql的路由规则去走
- cache_ttl:查询结果缓存的毫秒数
- timeout:这一类查询执行的的最大时间(毫秒),超时则自动kill。这是对后端DB的保护机制,相当于阿里云RDS的loose_max_statement_time变量的功能,但不同的是,阿里云这个变量的时间时不包括DML操作出现InnoDB行锁等待的时间,而ProxySQL的这个timeout是计算从发送sql到等待响应的时间。默认mysql-default_query_timeout是10h
- retries:语句在执行失败时,重试次数。默认由mysql-query_retries_on_failure变量指定为1。建议不要重试,有风险
- delay:查询延迟执行,这是ProxySQL提供的限流机制,会让其它的查询优先执行。默认值mysql-default_query_delay为0
- mirror_flagOUT,mirror_hostgroup:与镜像相关的设置
- error_msg:默认为NULL,如果指定了则这个查询直接被block掉,将error_msg返回给客户端
- multiplex:连接是否利用
- log:是否记录查询日志,可以看到log是否记录对象。要开启日志记录,需要设置变量mysql-eventslog_filename来指定文件名,然后这个log标记为1。但是目前proxysql记录的日志是二进制格式,需要特定的工具才能读取eventslog_reader_sample。这个工具在源码目录tools下面
创建规则
1、把所有以select 开头的语句全部分配到读组中,读组编号是20
2、把select … for update语句,这是一个特殊的select语句,会产生一个写锁(排他锁),把他分到编号为10的写组中,其他所有操作都会默认路由到写组中,select … for update规则的rule_id必须要小于普通的select规则的rule_id,因为ProxySQL是根据rule_id的顺序进行规则匹配的
insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (1,1,'^select.*for update$',10,1);
insert into mysql_query_rules(rule_id,active,match_pattern,destination_hostgroup,apply) values (2,1,'^select',20,1);
load mysql query rules to runtime;
save mysql query rules to disk;
测试读写分离
在ProxySQL节点上用对外服务端口连接ProxySQL,测试读是否给了读组
mysql -uproxysql -p123456 -P 6033 -h 192.168.1.51 -e “select @@server_id;”
可以看到只要是select操作都给了读组,下面测试下写操作
use mytest7;create table test (id int primary key auto_increment, name varchar(16));
start transaction;
insert into test values (1,'www');
select @@server_id;
select * from test for update;
select @@server_id;
在ProxySQL中查看路由信息,stats.stats_mysql_query_digest表中可以查看哪些sql频繁执行
select hostgroup,schemaname,username,digest_text,count_star from stats_mysql_query_digest;
- hostgroup:发送查询的主机组。值-1表示查询查询缓存
- schemaname:查询的数据库
- user:连接ProxySQL的用户名
- digest:一个十六进制散列,表示其参数剥离的SQL
- digest_text:参数剥离的实际SQL文本
- count_star:执行查询的总次数(参数的值不同)
- first_seen:unix时间戳,是通过代理路由查询的第一时刻
- last_seen:unix时间戳,当查询通过代理路由时的最后一刻(到目前为止)
- sum_time:执行此类查询的总时间(以微秒为单位),这对于应用程序工作负载中
花费的最多时间在哪里是非常有用的,并为改进的地方提供了一个良好的起点 - min_time,max_time:执行此类查询时期望的持续时间范围,min_time是到目前为止所看到的最小执行时间,而max_time表示最大执行时间,以微秒为单位
更改权重,比如让192.168.1.48承受更多的读操作
update mysql_servers set weight=10 hostname='192.168.1.48';
load mysql servers to runtime;
save mysql servers to disk;