proxysql配置mysql mgr代理,实现读写分离

项目背景

有三台服务器,已经完成搭建mysql mgr,实现主从组复制,现使用proxysql实现mysql的代理,实现读写分离。

mysql mgr 的安装配置查阅:https://blog.csdn.net/warton88/article/details/156905309?spm=1001.2014.3001.5501

服务器ip如下:

复制代码
mysql-master 192.168.133.129
mysql-slave1 192.168.133.130      
mysql-slave2 192.168.133.131

proxysql安装在  192.168.133.129

进入proxysql 管理命令界面

复制代码
root@mysql-master:~#  mysql -u admin -p -h 127.0.0.1 -P 6032  --prompt="admin>"
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.5.30 (ProxySQL Admin Module)

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

admin>

添加mysql所有节点到mysql_servers表

复制代码
admin>insert into mysql_servers(hostgroup_id,hostname,port) values (10,'192.168.133.129',3306);
Query OK, 1 row affected (0.00 sec)

admin>insert into mysql_servers(hostgroup_id,hostname,port) values (10,'192.168.133.130',3306);
Query OK, 1 row affected (0.00 sec)

admin>insert into mysql_servers(hostgroup_id,hostname,port) values (10,'192.168.133.131',3306);
Query OK, 1 row affected (0.00 sec)

# 默认分组 hostgroup_id = 10是主服务器,现在先配置上,后端会根据主从的实际情况自动调整


# 加载上述配置到运行时,就是热加载刚刚的配置
admin> LOAD MYSQL SERVERS TO RUNTIME;
Query OK, 0 rows affected (0.01 sec)

# 将刚刚的配置持久化存储到本地
admin>SAVE MYSQL SERVERS TO DISK;
Query OK, 0 rows affected (0.01 sec)

# 查验是否配置成功
admin>select * from mysql_servers;
+--------------+-----------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname        | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+-----------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 10           | 192.168.133.129 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 10           | 192.168.133.130 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 10           | 192.168.133.131 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+-----------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
3 rows in set (0.00 sec)

在mysql主节点上执行创建账户

复制代码
root@mysql-master:~# mysql -uroot -p
Enter password:  ......

# 创建proxysql用来监控mysql当前状态的账户
mysql> create user 'monitor'@'%' identified by 'monitor@1024!';
Query OK, 0 rows affected (0.19 sec)


# 创建应用用来连接proxysql代理的账户,后期应用不再直接使用mysql账户连接,使用此账户
mysql> create user 'proxysql_warton'@'%' identified by '@Password1122!';
Query OK, 0 rows affected (0.01 sec)


# 创建完之后可以在各个节点上查验新账户名
mysql> select host,user from mysql.user;
+-----------+------------------+
| host      | user             |
+-----------+------------------+
| %         | monitor          |
| %         | proxysql_warton  |
| %         | rpl_user         |
| %         | warton           |
| localhost | mysql.infoschema |
| localhost | mysql.session    |
| localhost | mysql.sys        |
| localhost | root             |
+-----------+------------------+
8 rows in set (0.00 sec)

# 给新账户赋权
mysql> grant all privileges on *.* to 'monitor'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> grant all privileges on *.* to 'proxysql_warton'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> flush privileges;
Query OK, 0 rows affected (0.01 sec)

在mysql主节点上执行创建gr_member_routing_candidata_state视图,这是主从故障切换的关键点

复制代码
mysql> use sys;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed

# 后续代码 直接复制执行
# 创建my_id 方法
create function my_id() returns text(36) deterministic no sql return (select @@global.server_uuid as my_id);

# 创建gr_member_in_primary_partition 方法,用来判断是不是主分区
DELIMITER //
CREATE FUNCTION gr_member_in_primary_partition()
RETURNS VARCHAR(3)
DETERMINISTIC
READS SQL DATA
BEGIN
    RETURN (
        SELECT 
            IF (
                MEMBER_STATE = 'ONLINE' AND (
                    (SELECT COUNT(*) FROM performance_schema.replication_group_members WHERE MEMBER_STATE NOT IN ('ONLINE', 'RECOVERING')) 
                    <= ((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2)
                ),
                'YES', 
                'NO'
            ) 
        FROM 
            performance_schema.replication_group_members 
        JOIN 
            performance_schema.replication_group_member_stats USING(member_id) 
        WHERE 
            member_id = my_id()
    );
END //
DELIMITER ;

# 主要用于为 ProxySQL 等中间件提供 MySQL 组复制(MGR)节点的监控状态指标,帮助判断节点是否适合作为路由候选节点‌
mysql> CREATE VIEW gr_member_routing_candidate_status AS SELECT 
    ->     sys.gr_member_in_primary_partition() AS viable_candidate,
    ->     IF( (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,
    ->     Count_Transactions_Remote_In_Applier_Queue AS transactions_behind,
    ->     Count_Transactions_in_queue as 'transactions_to_cert'
    -> FROM 
    ->     performance_schema.replication_group_member_stats 
    -> WHERE 
    ->     member_id = my_id();
Query OK, 0 rows affected (0.05 sec)

在proxysql中设置监控帐号跟程序帐号

复制代码
admin>set mysql-monitor_username='monitor';
Query OK, 1 row affected (0.00 sec)

admin>set mysql-monitor_password='monitor@1024!';
Query OK, 1 row affected (0.00 sec)

admin>insert into mysql_users(username,password,active,default_hostgroup,transaction_persistent) values ('proxysql_warton','@Password1122!',1,10,1);
Query OK, 1 row affected (0.00 sec)

在proxysql中设置mysql的读写分组

主负责写,从负责读,当MGR主库切换后,代理自动识别主从。

proxysql 代理每一个后端的MGR集群时,都必须要为这个MGR定义写组10,备写组20,读组30、离线组40,

注意:max_transactions_behind 是设置延迟的大小,可以给大点,建议自己去开个并行复制。

复制代码
admin>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) values (10,20,30,40,1,1,0,100);
Query OK, 1 row affected (0.00 sec)

启用规则

复制代码
# 直接复制粘贴
load mysql servers to runtime;
save mysql servers to disk;
load mysql users to runtime;
save mysql users to disk;
load mysql variables to runtime;
save mysql variables to disk;

校验配置

复制代码
admin>select hostgroup_id, hostname, port, status from runtime_mysql_servers;
+--------------+-----------------+------+--------+
| hostgroup_id | hostname        | port | status |
+--------------+-----------------+------+--------+
| 10           | mysql-master    | 3306 | ONLINE |
| 20           | 192.168.133.129 | 3306 | ONLINE |
| 30           | 192.168.133.130 | 3306 | ONLINE |
| 30           | 192.168.133.131 | 3306 | ONLINE |
| 30           | mysql-slave1    | 3306 | ONLINE |
| 30           | mysql-slave2    | 3306 | ONLINE |
+--------------+-----------------+------+--------+
6 rows in set (0.00 sec)

通过下面命令查看后台执行日志,如果有错误在error里面会显示出来

复制代码
admin>select hostname, port,viable_candidate,read_only,transactions_behind,error from mysql_server_group_replication_log order by time_start_us desc;
+-----------------+------+------------------+-----------+---------------------+-------+
| hostname        | port | viable_candidate | read_only | transactions_behind | error |
+-----------------+------+------------------+-----------+---------------------+-------+
| 192.168.133.131 | 3306 | YES              | YES       | 0                   | NULL  |
| mysql-master    | 3306 | YES              | NO        | 0                   | NULL  |
| mysql-slave2    | 3306 | YES              | YES       | 0                   | NULL  |
| mysql-slave1    | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.130 | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.129 | 3306 | YES              | NO        | 0                   | NULL  |
| 192.168.133.130 | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.131 | 3306 | YES              | YES       | 0                   | NULL  |
| mysql-master    | 3306 | YES              | NO        | 0                   | NULL  |
| mysql-slave1    | 3306 | YES              | YES       | 0                   | NULL  |
| mysql-slave2    | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.129 | 3306 | YES              | NO        | 0                   | NULL  |
| mysql-master    | 3306 | YES              | NO        | 0                   | NULL  |
| mysql-slave2    | 3306 | YES              | YES       | 0                   | NULL  |
| mysql-slave1    | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.130 | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.131 | 3306 | YES              | YES       | 0                   | NULL  |
| 192.168.133.129 | 3306 | YES              | NO        | 0                   | NULL  |
| mysql-slave1    | 3306 | YES              | YES       | 0                   | NULL  |

配置读写分离规则

复制代码
admin>insert into mysql_query_rules(rule_id, active, match_digest, destination_hostgroup, apply) values (1,1,'^SELECT.*FOR UPDATE$',10,1),(2,1,'^SELECT',30,1);
Query OK, 2 rows affected (0.00 sec)

# ProxySQL对于设置了会话变量的连接,
# 默认会通过mysql-set_query_lock_on_hostgroup参数将其锁定到特定主机组(如hostgroup 10)
# 而Navicat执行查询时可能尝试访问其他主机组(如hostgroup 30),从而触发冲突‌。
# 解决方法是调整ProxySQL配置,解除主机组查询锁:
mysql> set mysql-set_query_lock_on_hostgroup=0;
Query OK, 1 row affected (0.00 sec)

# 加载规则
admin>load mysql query rules to runtime;
Query OK, 0 rows affected (0.01 sec)

# 持久化规则
admin>save mysql query rules to disk;
Query OK, 0 rows affected (0.04 sec)

测试读写分离

使用proxysql连接6033,6033是代理端口

复制代码
root@mysql-master:~# mysql -u proxysql_warton -p -h 127.0.0.1 --prompt='write>'
Enter password: 
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 1309
Server version: 8.0.36 MySQL Community Server - GPL

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

WRITE>create database test;
Query OK, 1 row affected (0.01 sec)

WRITE>use test;
Database changed

write>create table test( n int primary key auto_increment) engine=innodb;
Query OK, 0 rows affected (0.01 sec)

write>insert into test values(1);
Query OK, 1 row affected (0.00 sec)

write>select * from test;
+---+
| n |
+---+
| 1 |
+---+
1 row in set (0.00 sec)

连接6032 端口查看日志

复制代码
root@mysql-master:~# mysql -uadmin -padmin -h 127.0.0.1 -P6032
mysql: [Warning] Using a password on the command line interface can be insecure.
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.5.30 (ProxySQL Admin Module)

Copyright (c) 2000, 2024, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> select hostgroup,digest_text from stats_mysql_query_digest order by digest_text desc limit 5;
+-----------+----------------------------------+
| hostgroup | digest_text                      |
+-----------+----------------------------------+
| 10        | show tables                      |
| 10        | show databases                   |
| 10        | select @@version_comment limit ? |
| 30        | select * from test               |
| 10        | insert into test values (?)      |
+-----------+----------------------------------+
5 rows in set (0.00 sec)
相关推荐
Run_Teenage1 小时前
Linux:匿名管道(实现个进程池)和命名管道
linux·运维·服务器
skywalk81631 小时前
Ubuntu22.04安装docker并启动 dnote服务
linux·ubuntu·docker·dnote
上天_去_做颗惺星 EVE_BLUE1 小时前
Android设备与Mac/Docker全连接指南:有线到无线的完整方案
android·linux·macos·adb·docker·容器·安卓
-dcr1 小时前
52.kubernetes基础
运维·云原生·kubernetes
BingoXXZ1 小时前
20260114Linux学习笔记
linux·服务器·笔记·学习
羊村积极分子懒羊羊1 小时前
软件管理(网络软件仓库的使用方法)
linux
匀泪1 小时前
CE(SELinux)
运维·服务器
Coder_Boy_1 小时前
基于SpringAI的在线考试系统-核心模块的数据模型交互关系
java·数据库·人工智能·spring boot·交互
better_liang2 小时前
Java技术栈中的MySQL数据结构应用与优化
java·数据结构·mysql·性能调优·索引优化