Proxysql|mysql读写分离

实验环境

主机名/IP角色
server01/192.168.1.201
server02/192.168.1.202
server03/192.168.1.203proxysql

主从同步部署请查阅:https://www.wakamizu.cn/mysql%e4%b8%bb%e4%bb%8e%e5%90%8c%e6%ad%a5/

服务基础配置

server01 && server02

创建测试用户

mysql -u root -p
create user testuser@'%' identified by 'wakamizu';
grant all privileges on world.* to testuser@'%';

创建监控用户

mysql -u root -p
CREATE USER 'monitor'@'%' IDENTIFIED BY 'monitor';
GRANT USAGE, REPLICATION CLIENT ON *.* TO 'monitor'@'%';

server03

安装

wget https://github.com/sysown/proxysql/releases/download/v2.7.0/proxysql_2.7.0-ubuntu22_amd64.deb
apt install -y ./proxysql_2.7.0-ubuntu22_amd64.deb
apt-get update -y
apt-get install proxysql mysql-client -y

启动服务

systemctl start proxysql

进入管理端

mysql -u admin -padmin -h 127.0.0.1 -P6032 --prompt 'ProxySQL Admin> '

添加mysql服务器

INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'192.168.1.201',3306);
INSERT INTO mysql_servers(hostgroup_id,hostname,port) VALUES (1,'192.168.1.202',3306);
SELECT * FROM mysql_servers;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1            | 192.168.1.201 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 1            | 192.168.1.202 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+

添加mysql连接凭据

UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_username';
UPDATE global_variables SET variable_value='monitor' WHERE variable_name='mysql-monitor_password';

配置临时生效

LOAD MYSQL VARIABLES TO RUNTIME;

配置持久化

SAVE MYSQL VARIABLES TO DISK;

查看mysql服务状态

SELECT * FROM mysql_servers;
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| hostgroup_id | hostname      | port | gtid_port | status | weight | compression | max_connections | max_replication_lag | use_ssl | max_latency_ms | comment |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1            | 192.168.1.201 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 1            | 192.168.1.202 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
SELECT * FROM monitor.mysql_server_connect_log ORDER BY time_start_us DESC LIMIT 2;
+---------------+------+------------------+-------------------------+---------------+
| hostname      | port | time_start_us    | connect_success_time_us | connect_error |
+---------------+------+------------------+-------------------------+---------------+
| 192.168.1.201 | 3306 | 1727018890913524 | 2427                    | NULL          |
| 192.168.1.202 | 3306 | 1727018890872968 | 2309                    | NULL          |
+---------------+------+------------------+-------------------------+---------------+
SELECT * FROM monitor.mysql_server_ping_log ORDER BY time_start_us DESC LIMIT 2;
+---------------+------+------------------+----------------------+------------+
| hostname | port | time_start_us | ping_success_time_us | ping_error |
+---------------+------+------------------+----------------------+------------+
| 192.168.1.201 | 3306 | 1727018906115823 | 528 | NULL |
| 192.168.1.202 | 3306 | 1727018906115822 | 319 | NULL |
+---------------+------+------------------+----------------------+------------+

创建主机组

如果mysql服务器的read_only=0,则转移到写入分组1;如果mysql服务器的read_only=1,则转移到仅读分组2;

INSERT INTO mysql_replication_hostgroups (writer_hostgroup,reader_hostgroup,comment) VALUES (1,2,'testcluster');
LOAD MYSQL SERVERS TO RUNTIME;
LOAD MYSQL USERS TO RUNTIME;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL SERVERS TO DISK;
SAVE MYSQL USERS TO DISK;
SAVE MYSQL QUERY RULES TO DISK;

可以前往mysql从服务器节点设置read_only为1,然后执行命令查看,可以看到运行时的服务器状态表已经显示配置生效:

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 |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+
| 1            | 192.168.1.201 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
| 2            | 192.168.1.202 | 3306 | 0         | ONLINE | 1      | 0           | 1000            | 0                   | 0       | 0              |         |
+--------------+---------------+------+-----------+--------+--------+-------------+-----------------+---------------------+---------+----------------+---------+

配置mysql用户

INSERT INTO mysql_users(username,password,default_hostgroup) VALUES ('testuser','wakamizu',1);
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK;
SELECT * FROM mysql_users;
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+------------+---------+
| username | password | active | use_ssl | default_hostgroup | default_schema | schema_locked | transaction_persistent | fast_forward | backend | frontend | max_connections | attributes | comment |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+------------+---------+
| testuser | wakamizu | 1      | 0       | 1                 | NULL           | 0             | 1                      | 0            | 1       | 1        | 10000           |            |         |
+----------+----------+--------+---------+-------------------+----------------+---------------+------------------------+--------------+---------+----------+-----------------+------------+---------+

测试连接

mysql -u testuser -p -h 192.168.1.203 -P 6033 

读写分离配置

删除规则

DELETE FROM mysql_query_rules;

使用不同端口进行读写分离

配置端口

SET mysql-interfaces='0.0.0.0:6401;0.0.0.0:6402';
SAVE MYSQL VARIABLES TO DISK;
PROXYSQL RESTART;

添加路由

INSERT INTO mysql_query_rules (rule_id,active,proxy_port,destination_hostgroup,apply) VALUES (1,1,6401,1,1), (2,1,6402,2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK; 

经过6401端口的流量全部访问写入分组1,经过6402端口的流量全部访问仅读分组2

使用正则表达式进行读写分离

UPDATE mysql_users SET default_hostgroup=1;
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply)
VALUES (1,1,'^SELECT',2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

先设置mysql用户默认分组为写入分组1,然后根据正则表达式将所有select开头的操作都分到仅读分组2

分析语句执行成本后用摘要和正则表达式进行读写分离

先将所有流量传输到一个服务器,然后分析执行成本大的语句进行路由
stats_mysql_query_digest表提供每个后端的查询计数、每个查询的响应时间以及实际查询文本以及查询摘要,查询摘要是每个查询类型的唯一标识符

根据总执行时间查找前五个查询:

SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY sum_time DESC LIMIT 5;

根据计数查找前五个查询:

SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY count_star DESC LIMIT 5;

根据最大执行时间查询前五个查询:

SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time,sum_time/count_star avg_time, min_time, max_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' ORDER BY max_time DESC LIMIT 5;

查找按总执行时间排序且最短执行时间至少为 1 毫秒的前 5五个查询:

SELECT digest,SUBSTR(digest_text,0,20),count_star,sum_time,sum_time/count_star avg_time, min_time, max_time FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' AND min_time > 1000 ORDER BY sum_time DESC LIMIT 5;

按总执行时间排序的前五个查询,平均执行时间至少为 1 秒,还显示总执行时间的百分比:

SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time,sum_time/count_star avg_time, ROUND(sum_time*100.00/(SELECT SUM(sum_time) FROM stats_mysql_query_digest),3) pct FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' AND sum_time/count_star > 1000000 ORDER BY sum_time DESC LIMIT 5;

按总执行时间排序的前五个查询,平均执行时间至少为 15 毫秒,并显示占总执行时间的百分比:

SELECT digest,SUBSTR(digest_text,0,25),count_star,sum_time,sum_time/count_star avg_time, ROUND(sum_time*100.00/(SELECT SUM(sum_time) FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%'),3) pct FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%' AND sum_time/count_star > 15000 ORDER BY sum_time DESC LIMIT 5;

接下来就可以将查询成本最大且重复多次的语句摘要转到仅读节点:

INSERT INTO mysql_query_rules (rule_id,active,digest,destination_hostgroup,apply)
VALUES
(1,1,'0x38BE36BDFFDBE638',2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

也可以评估所有SELECT COUNT(*)语句

SELECT digest,digest_text,count_star,sum_time,sum_time/count_star avg_time, 
       ROUND(sum_time*100.00/(SELECT SUM(sum_time) FROM stats_mysql_query_digest WHERE digest_text LIKE 'SELECT%'),3) pct 
FROM stats_mysql_query_digest 
WHERE digest_text LIKE 'SELECT COUNT%' ORDER BY sum_time DESC;

然后将所有以SELECT COUNT(*)开头的查询转移到仅读分组

INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply) VALUES (1,1,'^SELECT COUNT\(\*\)',2,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;

其他常用表

stats_mysql_connection_pool表显示与 MySQL 后端以及连接和总体流量相关的信息

SELECT * FROM stats.stats_mysql_connection_pool;

stats_mysql_commands_counters表返回有关执行的语句类型以及执行时间分布的详细信息

SELECT * FROM stats_mysql_commands_counters WHERE Total_cnt;

暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!