一、相关概念介绍:

1、MGR简介:

MySQL Group Replication(简称MGR)是MySQL官方推出的一种基于paxos协议的状态机复制,实现了分布式下数据的最终一致性。MySQL组复制提供了高可用、高扩展、高可靠的MySQL集群解决方案。相关网址https://dev.mysql.com/doc/refman/5.7/en/group-replication.html

2、MGR特性:

(1)高一致性:基于原生复制及paxos协议的组复制技术,并以插件的方式提供,保证数据一致性

(2)高容错性:只要不是大多数节点宕机就可以继续工作,有自动检测机制,当不同节点产生资源争用冲突时,不会出现错误,按照先到者优先原则进行处理,并且内置自动化脑裂防护机制

(3)高扩展性:节点的新增和移除都是自动的,新节点加入后,会自动从其它节点同步状态,直到新节点和其它节点保持一致,如果某节点被移除了,其它节点自动更新组信息

(4)高灵活性:有单主模式和多主模式,单主模式下会自动选择主节点,所有更新操作都在主节点上进行;多主模式下所有server都可以同时处理更新操

3、MGR局限性:

(1)仅支持InnoDB表,并且每张表一定要有一个主键,用于write set的冲突检测

(2)必须启用GTID特性,二进制日志格式必须设置为ROW,用于选主与write set

(3)COMMIT可能会导致失败,类似于快照事务隔离级别的失败场景

(4)目前一个MGR集群最多支持9个节点

(5)不支持外键于save point特性,无法做全局间的约束检测与部分回滚

(6)二进制日志不支持binlog event checksum

4、MGR集群架构:

image.png

5、MGR与其它复制方式的对比:

(1)MySQL异步复制:

master节点事务的提交不需要经过slave节点的确认,slave节点是否接收到master节点的binlogmaster节点并不关心。slave节点接收到master节点的binlog后先写relay log,最后异步地去执行relay log中的sql应用到本地。由于master节点的提交不需要确保slave节点的relay log是否被正确接收,当slave节点接收master节点的binlog失败或relay log应用失败,master节点无法感知。假设master节点发生宕机且binlog还未被slave节点接收,而切换程序将slave节点提升为新的master节点,就会出现数据不一致的情况。另外,在高并发的情况下,传统的主从复制,slave节点可能会与master节点产生较大的延迟。

image.png

(2)MySQL半同步复制:

基于传统异步复制存在的缺陷,MySQL5.5版本中推出半同步复制,可以说半同步复制是传统异步复制的改进,在master节点事务commit之前,必须确保一个slave节点收到relay log且响应给master节点以后,才能进行事务的commit,但是slave节点对于relay log的应用仍然是异步进行的。

image.png

(3)MySQL组复制:

基于传统异步复制和半同步复制的缺陷,即数据的一致性问题无法保证,MySQL官方在5.7.17版本中正式推出组复制(MySQL Group Replication,简称MGR)。由若干个节点共同组成一个复制组,一个事务的提交,必须经过组内大多数节点(N/2+1)决议并通过,才能得以提交。由三个节点组成一个复制组,Consensus层为一致性协议层,在事务提交过程中,发生组间通讯,由两个节点决议(certify)通过这个事务,事务才能最终得以提交并响应。一个复制组由若干个节点(数据库实例)组成,组内各个节点维护各自的数据副本,通过一致性协议实现原子消息和全局有序消息,来实现组内实例数据的一致。

image.png

6、ProxySQL简介:

ProxySQLMySQL的一款中间件产品,是灵活强大的MySQL代理层,可以实现读写分离,可自定义基于用户、基于schema、基于语句的规则对SQL语句进行路由,支持动态指定某个SQL进行缓存,支持动态加载配置、故障转移和一些SQL的过滤功能,可以实现简单的sharding

7、ProxySQL的多层配置系统:

ProxySQL有一套很完整的配置系统,方便DBA对线上的操作。整套配置系统分为三层,顶层为RUNTIME,中间层为MEMORY,底层也就是持久层的DISKCONFIG FILE。配置结构如下图所示:

image.png

(1)RUNTIMEProxySQL当前生效的生产环境正在使用的配置,包括global_variablesmysql_serversmysql_usersmysql_query_rules等,无法直接修改RUNTIME的配置,必须要从下一层“load”进来,也就是说RUNTIME这个顶级层,就是ProxySQL运行过程中实际采用的那一份配置,这一份配置就是要影响实际生产环境的。

(2)MEMORY:用户可以将MySQL客户端连接到此接口(admin接口),并查询不同的表和数据库是在MySQL命令行修改的main数据库中的配置,可以认为是SQLite数据库在内存的镜像,也就是说MEMORY这个中间层,上面连接着生产配置项RUNTIME层,下面连接着持久化层DISKCONFIG FILEMEMORY也是修改ProxySQL的唯一正常入口。修改一个配置一般都是先在MEMORY层完成,确认无误后再加载到RUNTIME和持久化到磁盘上,也就是说在这层可以正常操作ProxySQL配置,MEMORY层中的配置修改不会影响生产环境,也不影响磁盘中保存的数据,通过此接口可以修改main数据库中以mysql_开头的表(如:mysql_serversmysql_usersmysql_query_rules)和global_variables表等。

(3)DISKCONFIG FILE:持久化配置信息,一般保存在/var/lib/proxysql/proxysql.db数据文件中,重启后内存中的配置信息会丢失,所以需要将配置信息保留在磁盘中。重启时,可以从磁盘快速加载回来。配置文件/etc/proxysql.cnf只在第一次初始化时用到。DISKCONFIG FILE这一层是持久化层,做的任何配置更改,如果不持久化,重启后,配置将丢失。

8、ProxySQL相关网址:

(1)GitHub官网:https://github.com/sysown/proxysql/releases

(2)Percona官网:https://www.percona.com/downloads/proxysql/


二、准备工作(四个节点都需要执行如下操作):

1、 演示环境:

IP

操作系统

主机名

角色

软件包版本

安装方式

192.168.1.143

CentOS   7.6 x86_64

node1

proxysql

2.0.4-percona-1.2

yum

192.168.1.144

CentOS   7.6 x86_64

node2

master

5.7.26-log   MySQL Community Server

rpm

192.168.1.145

CentOS   7.6 x86_64

node3

slave1

5.7.26-log   MySQL Community Server

rpm

192.168.1.146

CentOS   7.6 x86_64

node4

slave2

5.7.26-log   MySQL Community Server

rpm

2、实验架构:

image.png

3、关闭SELinuxfirewalld

4、配置epel

5、配置节点时间同步

6、配置主机名

7、配置/etc/hosts文件:

# vim /etc/hosts

192.168.1.143 node1

192.168.1.144 node2

192.168.1.145 node3

192.168.1.146 node4

8、下载MySQL 5.7软件包,https://dev.mysql.com/downloads/mysql/5.7.html#downloads


三、构建MGR单主高可用集群(如未特殊说明,在masterslave1slave2节点中分别执行如下操作):

1、安装配置MySQL

(1)卸载CentOS 7.6自带的MariaDB

# rpm -qa | grep -i mariadb --> mariadb-libs-5.5.60-1.el7_5.x86_64

# rpm -e --nodeps mariadb-libs-5.5.60-1.el7_5.x86_64

(2)如果之前安装过MySQL,先卸载:# rpm -qa | grep -i mysql

(3)如果存在/etc/my.cnf配置文件,先删除:# rm -rf /etc/my.cnf

(4)将软件包上传至主机/tmp目录下:

mysql-community-client-5.7.26-1.el7.x86_64.rpm

mysql-community-libs-5.7.26-1.el7.x86_64.rpm

mysql-community-common-5.7.26-1.el7.x86_64.rpm

mysql-community-libs-compat-5.7.26-1.el7.x86_64.rpm

mysql-community-devel-5.7.26-1.el7.x86_64.rpm

mysql-community-server-5.7.26-1.el7.x86_64.rpm

(5)安装MySQL软件包:# yum -y localinstall *.rpm

(6)初始化MySQL数据:# mysqld --initialize --user=mysql --datadir=/var/lib/mysql

备注:初始化之前确保/var/lib/mysql目录为空

(7)修改MySQL配置文件:

# mv /etc/my.cnf /etc/my.cnf.bak

# vim /etc/my.cnf

master节点:

[mysqld]

port=3306

socket=/var/lib/mysql/mysql.sock

datadir=/var/lib/mysql

pid-file=/var/run/mysqld/mysqld.pid

log-error=/var/log/mysqld.log

lower_case_table_names=1

character_set_server=utf8mb4

collation_server=utf8mb4_general_ci

innodb_file_per_table=1

skip_name_resolve=1

slow_query_log=1

slow_query_log_file=mysql-slow.log

symbolic-links=0

explicit_defaults_for_timestamp=1

log_bin=mysql-bin

log_bin_index=mysql-bin.index

binlog_format=row

server_id=1

gtid_mode=on

enforce_gtid_consistency=on

master_info_repository=table

relay_log_info_repository=table

binlog_checksum=none

log_slave_updates=on

备注:

a、slave1节点中server_id=2,增加read_only=1,其它参数保持不变

b、slave2节点中server_id=3,增加read_only=1,其它参数保持不变

(8)启动MySQL服务:

# systemctl start mysqld.service

# ss -tunlp | grep mysqld

# systemctl enable mysqld.service

# systemctl status mysqld.service

(9)查看root@localhost用户的初始密码:# grep password /var/log/mysqld.log

(10)配置MySQL安全向导:# mysql_secure_installation

2、安装group_replication插件:

# mysql -uroot -p

mysql> install plugin group_replication soname 'group_replication.so';

mysql> show plugins;

image.png

备注:插件位于/usr/lib64/mysql/plugin/group_replication.so

3、修改MySQL配置文件,增加MGR相关配置:

# vim /etc/my.cnf

master节点:

[mysqld]

transaction_write_set_extraction=XXHASH64

group_replication_group_name='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa'

group_replication_start_on_boot=off

group_replication_local_address='192.168.1.144:24901'

group_replication_group_seeds='192.168.1.144:24901,192.168.1.145:24901,192.168.1.146:24901'

group_replication_bootstrap_group=off

group_replication_enforce_update_everywhere_checks=off

group_replication_single_primary_mode=on

# systemctl restart mysqld.service

备注1

(1)slave1节点中group_replication_local_address='192.168.1.145:24901',其它参数保持不变

(2)slave2节点中group_replication_local_address='192.168.1.146:24901',其它参数保持不变

备注2:参数说明

(1)gtid_mode=on:启用GTID模式

(2)enforce_gtid_consistency=on:启用强制GTID一致性

(3)master_info_repository=table:将master.info元数据保存在系统表中

(4)relay_log_info_repository=table:将relay.info元数据保存在系统表中

(5)binlog_checksum=none:禁用二进制日志事件校验

(6)log_slave_updates=on:启用级联复制

(7)transaction_write_set_extraction=XXHASH64:使用XXHASH64哈希算法将其编码为散列

(8)group_replication_group_name='aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa':加入或创建的组名称,值必须是有效的UUID

(9)group_replication_start_on_boot=offserver启动时不自动启动组复制

(10)group_replication_local_address='192.168.1.144:24901':该节点的MGR模块通信地址,自定义端口24901用于与组中的其它成员进行内部通信

(11)group_replication_group_seeds='192.168.1.144:24901,192.168.1.145:24901,192.168.1.146:24901':组成员的IP和端口

(12)group_replication_bootstrap_group=off:不执行MGR复制组的初始化操作,如果该参数设置为on,表示会创建一个MGR复制组,在此处master是第一个初始化节点,动态开启该参数,然后再启动MGR

(13)group_replication_enforce_update_everywhere_checks=off:该参数设置为off,表示启用单主模式,设置为on,表示启用多主模式

(14)group_replication_single_primary_mode=on:该参数设置为on,表示启用单主模式,设置为off,表示启用多主模式

4、创建具有复制权限的用户repluser

mysql> set sql_log_bin=0;

mysql> create user 'repluser'@'192.168.1.%' identified by '123456';

mysql> grant replication slave on *.* to 'repluser'@'192.168.1.%';

mysql> flush privileges;

mysql> set sql_log_bin=1;

备注:组复制使用异步复制协议来实现分布式恢复,在将组成员加入组之前将其同步,该用户为故障恢复的异步复制通道group_replication_recovery所用,复制通道用于在组成员之间传输事务

5、构建MGR集群:

mysql> change master to master_user='repluser',master_password='123456' for channel 'group_replication_recovery';

6、启动MGR集群:

master节点执行如下操作:

mysql> set global group_replication_bootstrap_group=on;

mysql> start group_replication;

mysql> set global group_replication_bootstrap_group=off;

slave1slave2节点分别执行如下操作,加入复制组:

mysql> set global group_replication_allow_local_disjoint_gtids_join=on;

mysql> start group_replication;

备注:

(1)set global group_replication_bootstrap_group=on:只需在master节点中执行,表示以后加入集群的成员以master节点为准,且只需执行一次

(2)set global group_replication_bootstrap_group=off:确保master节点下一次启动时不会再进行初始化,导致复制组出现分裂

7、查看MGR状态信息:

mysql> select * from performance_schema.replication_group_members;

image.png

备注:按照MEMBER_ID进行升序排序,每个节点执行结果相同

mysql> select * from performance_schema.replication_connection_status\G

master节点:

image.png

slave1节点:

image.png

slave2节点:

image.png

mysql> show global variables like '%group_replication%';

mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;

master节点:

image.png

备注:is_primary_mode的值为1说明此节点为master节点

slave1节点:

image.png

slave2节点:

image.png

8、master节点创建测试数据:

mysql> create database db;

mysql> use db;

mysql> create table tb(id int unsigned auto_increment primary key not null,age int not null);

mysql> desc tb;

mysql> insert into tb(age) values(35),(40);

mysql> select * from tb;

image.png

9、slave1slave2节点分别查看测试数据:

mysql> show databases like 'db';

image.png

mysql> select * from db.tb;

image.png


四、安装配置ProxySQL(如未特殊说明,在proxysql节点中执行如下操作):

1、配置percona源:

# yum -y install https://repo.percona.com/yum/percona-release-latest.noarch.rpm

# yum repolist

2、安装MySQL客户端工具:# yum -y install Percona-Server-client-57

3、安装ProxySQL# yum list | grep -i percona  # yum -y install proxysql2  # proxysql --version

image.png

备注:ProxySQL相关文件

(1)配置文件:/etc/proxysql-admin.cnf/etc/proxysql.cnf

(2)SQLite数据文件:/var/lib/proxysql/proxysql.db

(3)日志文件:/var/lib/proxysql/proxysql.log

备注:如果存在proxysql.db数据文件,则ProxySQL启动过程中将不会读取proxysql.cnf配置文件的内容来初始化ProxySQL

4、启动ProxySQL

# systemctl start proxysql.service

# ss -tunlp | grep proxysql

image.png

备注:6032ProxySQL的管理端口号,6033是对外服务的端口号

5、使用默认的admin用户(密码也为admin)登录ProxySQL管理界面:

# mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> '

备注:如果需要创建一个新用户marion,密码为123456,则可执行如下操作

proxysql> update global_variables set variable_value='admin:admin;marion:123456' where variable_name='admin-admin_credentials';

proxysql> load admin variables to runtime;

proxysql> save admin variables to disk;

备注:无论执行任何操作,都需要执行load *** to runtime(从memory加载到runtime)、save *** to disk(持久化到磁盘)

6、master节点创建ProxySQL的监控用户monitor和对外访问用户proxysql,并赋予权限:

mysql> create user 'monitor'@'192.168.1.%' identified by '123456';

mysql> grant all on *.* to 'monitor'@'192.168.1.%';

mysql> create user 'proxysql'@'192.168.1.%' identified by '123456';

mysql> grant all on *.* to 'proxysql'@'192.168.1.%';

mysql> flush privileges;

7、添加主从服务器列表:

proxysql> insert into mysql_servers(hostgroup_id,hostname,port,weight,comment) values(10,'192.168.1.144',3306,1,'master'),(10,'192.168.1.145',3306,1,'slave1'),(10,'192.168.1.146',3306,3,'slave2');

proxysql> load mysql servers to runtime;

proxysql> save mysql servers to disk;

proxysql> select * from mysql_servers;

image.png

备注:

(1)mysql_servers:后端可以连接MySQL主机的列表

(2)所有节点都是ONLINE状态

(3)slave2节点的查询权重调整为3,为了让更多的读请求路由到这台配置更好的主机上

(4)mysql_servers常用字段说明:

字段

说明

hostgroup_id

ProxySQL通过hostgroup的形式组织后端db实例,一个hostgroup代表同属于一个角色,默认为0

hostname

后端实例IP

port

后端实例监听端口,默认为3306

status

后端实例状态,默认为online,可取值为:

Ø   online:当前后端实例状态正常

Ø   shunned:临时被剔除,可能因为后端too many connections error,或者超过了可容忍延迟阀值max_replication_lag

Ø   offline_soft:“软离线”状态,不再接收新的连接,但已建立的连接会等待活跃事务完成

Ø   offline_hard:“硬离线”状态,不再接收新的连接,已建立的连接或被强制中断,当后端实例宕机或网络不可达时,会出现

weight

后端实例权重,默认为1

max_connections

允许连接到该后端实例的最大连接数,不能大于MySQL设置的max_connections,如果后端实例hostname:port在多个hostgroup中,以较大者为准,而不是各自独立允许的最大连接数,默认为1000

max_replication_lag

允许的最大延迟,master节点不受此影响,默认为0,如果>0monitor模块监控主从延迟大于阀值时,会临时把它变为shunned

max_latency_ms

mysql_ping响应时长,大于这个阀值会把它从连接池中剔除(即使是ONLINE状态),默认为0

comment

备注

(5)查看表中的字段可使用命令proxysql> show create table mysql_servers\G

(6)查看表中的数据可使用命令proxysql> select * from mysql_servers\G

8、配置和注册监控用户monitor,并验证监控信息:

proxysql> set mysql-monitor_username='monitor';

proxysql> set mysql-monitor_password='123456';

proxysql> load mysql variables to runtime;

proxysql> save mysql variables to disk;

proxysql> select * from global_variables where variable_name in ('mysql-monitor_username','mysql-monitor_password');

image.png

proxysql> select * from monitor.mysql_server_connect_log order by time_start_us desc limit 6;

image.png

proxysql> select * from monitor.mysql_server_ping_log order by time_start_us desc limit 6;

image.png

9、配置ProxySQL主从分组信息:

proxysql> insert into mysql_replication_hostgroups values (10,20,'read_only','proxysql');

proxysql> load mysql servers to runtime;

proxysql> save mysql servers to disk;

备注:

(1)mysql_replication_hostgroups常用字段说明:

字段

说明

writer_hostgroup

写入组的编号,此处为10

reader_hostgroup

读取组的编号,此处为20

check_type

可取值为:'read_only''innodb_read_only''super_read_only',默认值为'read_only'

comment

备注

(2)查看表中的字段可使用命令proxysql> show create table mysql_replication_hostgroups\G

(3)查看表中的数据可使用命令proxysql> select * from mysql_replication_hostgroups\G

proxysql> select * from mysql_replication_hostgroups;

image.png

proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;

image.png

备注:ProxySQL会根据MySQLread_only的取值将主机进行分组,read_only=0master节点被分配到编号为10的写入组,而read_only=1的两个slave节点则被分配到编号为20的读取组

10、配置对外访问用户proxysql

proxysql> insert into mysql_users(username,password,default_hostgroup) values('proxysql','123456',10);

proxysql> load mysql users to runtime;

proxysql> save mysql users to disk;

proxysql> select * from mysql_users\G

image.png

备注:

(1)mysql_users:配置后端数据库用户和监控用户

(2)mysql_users常用字段说明:

字段

说明

username

前端连接ProxySQL,及ProxySQLSQL语句路由给后端MySQL实例中所使用的用户名

password

后端MySQL实例中用户名对应的密码,可以是明文密码,也可以是hash加密后的密文,如果想使用hash密码,可以先在某个MySQL节点中执行select password(PASSWORD),然后将加密结果复制到该字段

active

只有active=1的用户才是有效的用户

default_hostgroup

该用户名默认的路由目标,如:指定root用户的该字段值为10时,则使用root用户发送的SQL语句默认情况下将路由到hostgroup_id=10组中的某个节点,如果该用户的请求没有匹配到规则时,默认发送到这个hostgroup

default_schema

用户默认登录后端MySQL实例时连接的数据库,如果为NULL,则由全局变量mysql-default_schema决定,默认为information_schema

transaction_persistent

默认为1,表示启用事务持久化,连接上ProxySQL的会话后,如果在一个hostgroup中开启了事务,那么在事务提交/回滚之前,所有的语句都路由到同一个组中,无论是否会匹配上其它路由规则,直到事务结束,避免语句分散到不同组(更进一步的,它会自动禁用multiplexing,让同一个事务的语句从同一个连接路由出去,保证路由到同一个组的同一个节点),避免发生脏读、幻读等情况

(3)查看表中的字段可使用命令proxysql> show create table mysql_users\G

(4)查看表中的数据可使用命令proxysql> select * from mysql_users\G

11、验证通过对外服务6033端口登录的是master节点:

# mysql -uproxysql -p -h192.168.1.143 -P6033 -e 'select @@hostname;'

image.png

备注:node2master节点的主机名

12、配置路由规则,实现读写分离:

proxysql> insert into mysql_query_rules(active,match_pattern,destination_hostgroup,apply) values(1,'^select.*for update$',10,1),(1,'^select',20,1);

proxysql> load mysql query rules to runtime;

proxysql> save mysql query rules to disk;

proxysql> select rule_id,active,match_pattern,destination_hostgroup,apply from mysql_query_rules;

image.png

备注:

(1)select for update会产生一个写锁,对数据查询的时效性要求较高,所以将它分配到编号为10的写入组

(2)除了select for update以外所有select开头的语句全部分配到编号为20的读取组

(3)其它所有操作都默认路由到写入组(mysql_users表中字段default_hostgroup定义的值)

(4)mysql_query_rules:指定query路由到后端不同主机的规则列表

(5)mysql_query_rules常用字段说明:

字段

说明

rule_id

表主键,自增,规则处理是以rule_id的顺序进行

active

默认为0,值为1时表示启用此路由规则

username

如果不为空,该规则只匹配该用户

schemaname

如果不为空,该规则只匹配该数据库名称,如果为NULL,不代表连接没有使用schema,而是无论任何schema都进一步匹配

client_addr

匹配客户端来源IP

proxy_addr

匹配本地ProxySQLIP

proxy_port

匹配本地ProxySQL的端口

match_digest

描述规则的正则表达式,1.4版本以后,正则表达式支持pcrepcre2两种,默认使用pcre,即perl语言支持的正则表达式,query   digest是指对查询去掉具体值后进行“模糊化”后的查询

match_pattern

正则表达式匹配查询

negate_match_pattern

反向匹配,相当于对match_digest/match_pattern的匹配取反,默认为0

re_modifiers

修改正则匹配的参数,如默认的:忽略大小写CASELESS、禁用GLOBAL,默认为CASELESS

destination_hostgroup

该路由规则发往哪个组

cache_ttl

用户查询缓存的时间阈值,单位为毫秒

timeout

这一类查询执行的最大时间(单位为毫秒),超时则自动kill,这是对后端db的保护机制,默认mysql-default_query_timeout的值是10h

retries

语句在执行失败时,重试的次数,默认由mysql-query_retries_on_failure变量指定,默认为1

delay

查询延迟执行,这是ProxySQL提供的限流机制,会让其它的查询优先执行

apply

默认为0,值为1时表示该正则匹配后,将不再接受其它匹配,直接转发

comment

备注

(6)查看表中的字段可使用命令proxysql> show create table mysql_query_rules\G

(7)查看表中的数据可使用命令proxysql> select * from mysql_query_rules\G

13、ProxySQL中的内置数据库及常用表、字段说明:

proxysql> show databases;

image.png

备注:默认已处于main数据库中

(1)main:内存配置数据库,即memory,表中存放后端db实例、用户验证、路由规则等信息

查看main数据库中的表:proxysql> show tables from main;

image.png

备注:表名以runtime_开头的表示ProxySQL当前正在运行的配置内容,不能通过DML语句修改,但能从其它层级加载,只能修改对应的不以runtime_开头的表,然后load *** to runtime(从memory加载到runtime)、save *** to disk(持久化到磁盘)

(2)disk:持久化到磁盘的配置,SQLite数据文件

查看disk数据库中的表:proxysql> show tables from disk;

(3)statsProxySQL将收集的统计数据存储在stats数据库中,包括到后端各命令的执行次数、流量、processlist、查询种类汇总/执行时间等等

查看stats数据库中的表:proxysql> show tables from stats;

a、stats_mysql_commands_counters:统计各种SQL类型的执行次数和时间

stats_mysql_commands_counters常用字段说明:

字段

说明

Command

已执行的SQL命令的类型,如:FLUSHINSERTKILLSELECT

Total_Time_us

执行该类型命令的总时间(以微秒为单位)

Total_cnt

执行该类型命令的总数

cnt_100uscnt_500uscnt_1mscnt_5mscnt_10mscnt_50mscnt_100mscnt_500mscnt_1scnt_5scnt_10scnt_INFs

在指定的时间内执行该类型的命令总数和前一个命令的总数

 b、stats_mysql_connection_pool:连接后端MySQL的连接池信息

stats_mysql_connection_pool常用字段说明:

字段

说明

hostgroup

后端主机所属的主机组,单个后端主机可以属于多个主机组

srv_host

后端主机正在侦听连接的IP

srv_port

后端主机正在侦听连接的TCP Port

status

后端实例状态,默认为online,可取值为:

Ø   online:当前后端实例状态正常

Ø   shunned:临时被剔除,可能因为后端too many connections error,或者超过了可容忍延迟阀值max_replication_lag

Ø   offline_soft:“软离线”状态,不再接收新的连接,但已建立的连接会等待活跃事务完成

Ø   offline_hard:“硬离线”状态,不再接收新的连接,已建立的连接或被强制中断,当后端实例宕机或网络不可达时,会出现

ConnUsed

ProxySQL当前使用多少个连接来向后端主机发送查询

ConnFree

目前有多少个空闲连接

ConnOK

成功建立了多少个连接

ConnERR

没有成功建立多少个连接

Queries

路由到此特定后端主机的查询数

Bytes_data_sent

发送到后端主机的数据量

Bytes_data_recv

从后端主机接收的数据量

Latency_us

monitor报告的当前ping(以毫秒为单位)的延迟时间

c、stats_mysql_global:与MySQL相关的代理级别的全局统计

stats_mysql_global常用字段说明:

字段

说明

Client_Connections_aborted

由于无效凭据或max_connections而导致的前端连接数已达到

Client_Connections_connected

当前连接的前端连接数

Client_Connections_created

到目前为止创建的前端连接数

Questions

从前端发送的查询总数

Slow_queries

在全局变量中定义的运行时间超过阈值的毫秒数的查询数mysql-long_query_time

d、stats_mysql_processlist:类似MySQLshow processlist的命令,查看各线程的状态

stats_mysql_processlist常用字段说明:

字段

说明

ThreadID

ProxySQL线程ID

SessionID

ProxySQL会话ID,通过此ID可以进行kill操作

user

通过MySQL客户端连接ProxySQL的用户

db

当前选择的数据库

cli_host

连接ProxySQLMySQL客户端IP

cli_port

连接ProxySQLTCP端口

hostgroup

当前主机组,如果正在处理查询,则是查询已被路由或将要路由的主机组,或默认主机组,可以查看该SQL到底是路由到哪个主机组中

l_srv_host

ProxySQLIP

l_srv_port

ProxySQLTCP端口

srv_host

后端MySQL服务器的IP

srv_port

后端MySQL服务器的TCP端口

command

正在执行的MySQL查询类型

time_ms

命令执行的时长(以毫秒为单位)

info

正在执行的SQL

e、stats_mysql_query_rules:统计路由命中次数

stats_mysql_query_rules常用字段说明:

字段

说明

rule_id

路由规则的idmain.mysql_query_rulesid对应

hits

此路由规则的匹配总数,如果当前传入的查询符合规则,则会记录一次命中

(4)monitor:存储monitor模块收集的信息,主要是对后端db的健康/延迟检查

查看monitor数据库中的表:proxysql> show tables from monitor;

表名

说明

mysql_server_connect_log

连接所有MySQL主机以检查它们是否可用,该表用来存放检测连接的日志,由变量mysql-monitor_connect_interval来控制其检测的时间间隔,由参数mysql-monitor_connect_timeout控制连接是否超时(默认为200毫秒)

mysql_server_ping_log

使用mysql_ping API ping后端MySQL主机检查它们是否可用,该表用来存放ping的日志,由变量mysql-monitor_ping_interval控制ping的时间间隔,默认为10000(单位毫秒,相当于10秒)

mysql_server_replication_lag_log

后端MySQL服务主从延迟的检测,由参数mysql-monitor_replication_lag_interval控制检测时间间隔,由mysql_servers.max_replication_lag列控制,默认为10000(单位毫秒,相当于10秒)

备注:

a、查看表中的字段可使用命令proxysql> show create table 表名\G

b、查看表中的数据可使用命令proxysql> select * from 表名\G


五、测试ProxySQL

1、测试读写分离:

(1)清空stats_mysql_query_digest表:

# mysql -uadmin -p -h127.0.0.1 -P6032 --prompt='proxysql> '

proxysql> select * from stats_mysql_query_digest_reset;

proxysql> select * from stats_mysql_query_digest;

image.png

# mysql -uproxysql -p -h192.168.1.143 -P6033

mysql> select * from db.tb;

image.png

mysql> insert into db.tb(age) values(0),(100);

mysql> select * from db.tb for update;

image.png

备注:

a、stats_mysql_query_digestSQL的执行次数、时间消耗等

b、stats_mysql_query_digest常用字段说明:

字段

说明

hostgroup

发送查询的主机组,值为-1表示查询的是查询缓存

schemaname

查询的数据库

username

连接ProxySQL的用户名

digest_text

参数剥离的实际SQL文本

count_star

执行查询的总次数

first_seen

unix时间戳,查询通过代理路由查询的第一时刻

last_seen

unix时间戳,查询通过代理路由查询的最后一刻(到目前为止)

sum_time

执行此类查询的总时间(以微秒为单位)

min_time

执行此类查询时期望的持续时间范围,min_time表示到目前为止所看到的最小执行时间

max_time

执行此类查询时期望的持续时间范围,max_time表示最大执行时间,以微秒为单位

c、查看表中的字段可使用命令proxysql> show create table stats.stats_mysql_query_digest\G

d、查看表中的数据可使用命令proxysql> select * from stats.stats_mysql_query_digest\G

e、stats_mysql_query_digest_reset和表stats_mysql_query_digest结构一致

(2)通过查询stats_mysql_query_digest表来监控查询状态:

proxysql> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest;

image.png

备注:

a、select * from tb for update语句已经自动路由到编号为10的写入组,即master节点

b、select * from tb语句已经自动路由到编号为20的读取组,即slave节点

2、测试读请求负载均衡:

# for i in {1..12}; do mysql -uproxysql -p123456 -h192.168.1.143 -P6033 -e 'select @@hostname' -s -N; done

选项说明:

(1)-s:以制表符作为分隔符打印结果

(2)-N:结果中不包含列名

备注:上述命令执行结果可得出读请求在两台slave节点间切换,且node3node4的出现比例接近1:3

3、测试ProxySQL故障转移:

(1)单主模型脚本gr_sw_mode_checker.shhttps://github.com/ZzzCrazyPig/proxysql_groupreplication_checker

备注:共有三个脚本提供下载

a、proxysql_groupreplication_checker.sh:用于multi-primary模式,可以实现读写分离及故障转移,同一时间点多个节点都可以写

b、gr_mw_mode_cheker.sh:用于multi-primary模式,可以实现读写分离及故障转移,但在同一时间点只能有一个节点可以写

c、gr_sw_mode_checker.sh:用于single-primary模式,可以实现读写分离及故障转移

(2)将下载的脚本gr_sw_mode_checker.sh放置至/var/lib/proxysql目录中,并赋予执行权限和修改属主属组:

# chmod +x /var/lib/proxysql/gr_sw_mode_checker.sh

# chown proxysql.proxysql /var/lib/proxysql/gr_sw_mode_checker.sh

(3)下载addition_to_sys.sqlhttps://github.com/lefred/mysql_gr_routing_check/

(4)master节点创建表sys.gr_member_routing_candidate_status# mysql -uroot -p < addition_to_sys.sql

mysql> select * from sys.gr_member_routing_candidate_status;

master节点:

image.png

slave1节点:

image.png

slave2节点:

image.png

(5)配置scheduler

proxysql> insert into scheduler(active,interval_ms,filename,arg1,arg2,arg3,arg4) values(1,5000,'/var/lib/proxysql/gr_sw_mode_checker.sh',10,20,1,'/var/lib/proxysql/gr_sw_mode_checker.log');

proxysql> load scheduler to runtime;

proxysql> save scheduler to disk;

备注1

a、scheduler常用字段说明

字段

说明

active

值为1时允许计划程序定期执行提供的脚本,默认为1

interval_ms

每隔多少毫秒执行一次脚本,5000毫秒为5

filename

脚本的存放路径

arg1~arg4

脚本接收到的输入参数

comment

备注

b、查看表中的字段可使用命令proxysql> show create table scheduler\G

c、查看表中的数据可使用命令proxysql> select * from scheduler\G

d、问题排查可查看日志文件/var/lib/proxysql/gr_sw_mode_checker.log

备注2:脚本gr_sw_mode_checker.sh用法

gr_sw_mode_cheker.sh <hostgroup_id write> <hostgroup_id read> [write node can be read : 1(YES: default) or 0(NO)] [log_file]

a、arg1hostgroup_id write

b、arg2hostgroup_id read

c、arg3write node can be read : 1(YES: default) or 0(NO)

d、arg4log_file, default: './checker.log'

proxysql> select * from scheduler\G

image.png

(6)查MGR状态信息:

proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;

image.png

mysql> select * from performance_schema.replication_group_members;

image.png

mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;

master节点:

image.png

备注:is_primary_mode的值为1说明此节点为master节点

slave1节点:

image.png

slave2节点:

image.png

(7)master节点模拟MySQL服务故障:# systemctl stop mysqld.service

(8)查看MGR状态信息:

proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;

image.png

mysql> select * from performance_schema.replication_group_members;

image.png

mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;

slave1节点:

image.png

slave2节点:

image.png

备注:当master节点意外宕机或下线,在满足大多数节点存活的情况下,group内部发起选举,选出下一个可用的读节点,提升其为master节点。master节点选举根据group内剩余存活节点的UUID按字典升序排列,然后选择排在最前的节点作为新的master节点。is_primary_mode的值为1说明slave2节点已经被选举为新的master节点。

mysql> select * from sys.gr_member_routing_candidate_status;

slave1节点:

image.png

slave2节点:

image.png

备注:slave2节点中的read_only参数的值已经自动修改为0

(9)slave2节点创建测试数据:

mysql> insert into db.tb(age) values(60),(80);

mysql> select * from db.tb;

image.png

(10)slave1节点查看测试数据:

mysql> select * from db.tb;

image.png

(11)master节点恢复MySQL服务:# systemctl start mysqld.service

(12)master节点加入复制组:mysql> start group_replication;

(13)查看MGR状态信息:

proxysql> select hostgroup_id,hostname,port,status,weight,comment from mysql_servers;

image.png

mysql> select * from performance_schema.replication_group_members;

image.png

mysql> select if((select @@server_uuid)=(select variable_value from performance_schema.global_status where variable_name='group_replication_primary_member'),1,0) as is_primary_mode,@@server_id;

master节点:

image.png

备注:新上线的原master节点现已变为slave节点

slave1节点:

image.png

slave2节点:

image.png

mysql> select * from sys.gr_member_routing_candidate_status;

master节点:

image.png

备注:原master节点中的read_only参数的值已经自动修改为1

slave1节点:

image.png

slave2节点:

image.png

(14)master节点已经复制了最新的测试数据:

mysql> select * from db.tb;

image.png

4、使用sysbench进行压测:

(1)安装sysbench# yum -y install sysbench

(2)将用户proxysqltransaction_persistent值修改为0

proxysql> update mysql_users set transaction_persistent=0 where username='proxysql';

proxysql> load mysql users to runtime;

proxysql> save mysql users to disk;

(3)prepare

# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua prepare

image.png

备注:常用选项说明

a、--threads:使用的线程数

b、--events:事件总数

c、--time:以秒为单位的总执行时间

d、--report-interval:以秒为单位定期报告具有指定间隔的中间统计信息

e、--mysql-hostProxySQL所在主机的IP

f、--mysql-portProxySQL对外服务的端口号

g、--mysql-userMySQL user

h、--mysql-passwordMySQL password

i、--mysql-db:在db数据库中创建表sbtest1,并插入10000条数据

(4)run

# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua run

image.png

备注:不要Ctrl + c终止压测

(5)压测过程中复制会话,观察读写分离状态:

proxysql> select hostgroup,schemaname,username,digest_text from stats_mysql_query_digest\G

备注:上述命令执行结果可得出写请求都路由到编号为10的写入组,而读请求都路由到编号为20的读取组

5、测试查询缓存:

ProxySQL的查询缓存和MySQL的查询缓存有点类似,但不完全一样,ProxySQL的查询缓存如果在指定时间大小范围内发送的SQL一摸一样,那么直接返回结果集,而返回的结果集可能并不是准确的查询结果,所以需要设置合适的时间范围,既能提升性能,又得满足业务需求,即查询结果足够的“新”。针对一些查询频率很高但结果并不需要太精确的业务,可以单独给这些SQL配置查询缓存。

(1)启用查询缓存:

proxysql> update mysql_query_rules set cache_ttl=2000 where active=1 and destination_hostgroup=20;

proxysql> load mysql query rules to runtime;

proxysql> save mysql query rules to disk;

(2)压测:

# sysbench --threads=8 --events=100000000 --time=2000 --report-interval=5 --mysql-host=192.168.1.143 --mysql-port=6033 --mysql-user=proxysql --mysql-password=123456 --mysql-db=db /usr/share/sysbench/tests/include/oltp_legacy/oltp.lua run

(3)压测过程中复制会话,观察读写分离状态:

proxysql> select hostgroup,digest_text,sum_time from stats_mysql_query_digest\G

image.png

备注:可以看到hostgroup的值部分为-1,表示这些查询使用了查询缓存,且耗时为0

6、启用Web统计功能:

(1)查看变量admin-web_enabled是否启用:

proxysql> select * from global_variables where variable_name like 'admin-web%';

image.png

(2)启用变量admin-web_enabled

proxysql> set admin-web_enabled='true';

proxysql> load admin variables to runtime;

proxysql> save admin variables to disk;

proxysql> select * from global_variables where variable_name like 'admin-web%';

image.png

(3)查看登录Web界面的用户名、密码和端口:

proxysql> select * from global_variables where variable_name like 'admin-web%' or variable_name LIKE 'admin-stats%';

image.png

(4)浏览器中访问192.168.1.143:6080,用户名和密码均为stats

image.png

image.png

image.png

image.png

image.png