项目背景
有三台服务器,已经完成搭建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)