1.ProxySQL采用不同的端口实现读写分离
先说缺点,采用该方案应用程序需要内置读写分离的能力,以便区分读和写。
配置ProxySQL监听在两个不同的端口,方法如下:
# ProxySQL 默认的用于客户端连接的端口是6033
ProxyQL-Admin> show variables like 'mysql-interfaces';
+------------------+--------------+
| Variable_name | Value |
+------------------+--------------+
| mysql-interfaces | 0.0.0.0:6033 |
+------------------+--------------+
ProxyQL-Admin> set mysql-interfaces="0.0.0.0:6401;0.0.0.0:6402";
ProxyQL-Admin> save mysql variables to disk;
ProxyQL-Admin> proxysql restart;
ProxyQL-Admin> show variables like 'mysql-interfaces';
+------------------+---------------------------+
| Variable_name | Value |
+------------------+---------------------------+
| mysql-interfaces | 0.0.0.0:6401;0.0.0.0:6402 |
+------------------+---------------------------+
添加通过入站端口的路由:
write :6401 (hostgroup_id=1)
read :6402 (hostgroup_id=2)
ProxyQL-Admin> insert into mysql_query_rules(rule_id,active,proxy_port,destination_hostgroup,apply) values (1,1,6401,1,1),(2,1,6402,2,1);
ProxyQL-Admin> load mysql query rules to runtime;
ProxyQL-Admin> save mysql query rules to disk;
ProxyQL-Admin> select * from mysql_query_rules;
ProxyQL-Admin> select * from runtime_mysql_query_rules;
现在所有连接端口6401的客户端,发送的SQL将被发送到主机组1中的MySQL服务器,而所有连接端口6402的客户端,发送的SQL将被发送到主机组2中的一个MySQL服务器。
#通过连接ProxySQL的6401连接后端的MySQL主库:
mysql -ustnduser -p -P6401 -h 192.168.1.100
#通过连接ProxySQL的6402连接后端的MySQL从库:
mysql -ustnduser -p -P6402 -h 192.168.1.100
2.通过正则表达式实现读写分离
#删除之前创建的读写分离规则:
ProxyQL-Admin> delete from mysql_query_rules;
#创建规则(mysql_users表中的用户默认hostgroup_id为1)
1)首先配置ProxySQL,将所有的流量发送到一个MySQL节点,即主节点
2)分析stats_mysql_query_digest表,然后找到查询最多的select语句
3)确定哪些SQL语句对于路由到从节点是安全的(比如对延迟不敏感的)
4)配置mysql_query_rules表,将这些查询最多的select语句发送到从库
2.1通过分析stats_mysql_query_digest表来获取select最多的SQL
#查找基于总执行时间的前5个查询
ProxyQL-Admin> 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;
+--------------------+--------------------------+------------+----------+
| digest | substr(digest_text,0,25) | count_star | sum_time |
+--------------------+--------------------------+------------+----------+
| 0x250cb4007721d69 | SELECT c FROM sbtest3 WH | 9584 | 12767018 |
| 0x9af59b998a3688ed | SELECT c FROM sbtest2 WH | 9494 | 12570443 |
| 0xbf001a0c13781c1d | SELECT c FROM sbtest1 WH | 8914 | 11861321 |
| 0xc19480748ae79b4b | SELECT DISTINCT c FROM s | 937 | 3783683 |
| 0x44bcb144058686eb | SELECT DISTINCT c FROM s | 940 | 3711176 |
+--------------------+--------------------------+------------+----------+
#查找基于总执行次数的前5个查询
ProxyQL-Admin> 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 l
imit 5;
+--------------------+--------------------------+------------+----------+
| digest | substr(digest_text,0,25) | count_star | sum_time |
+--------------------+--------------------------+------------+----------+
| 0x250cb4007721d69 | SELECT c FROM sbtest3 WH | 9584 | 12767018 |
| 0x9af59b998a3688ed | SELECT c FROM sbtest2 WH | 9494 | 12570443 |
| 0xbf001a0c13781c1d | SELECT c FROM sbtest1 WH | 8914 | 11861321 |
| 0xdbf868b2aa296bc5 | SELECT SUM(k) FROM sbtes | 975 | 1655437 |
| 0xac80a5ea0101522e | SELECT c FROM sbtest1 WH | 974 | 3518589 |
+--------------------+--------------------------+------------+----------+
#查找基于最大执行时间的前5个查询
ProxyQL-Admin> 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;
+--------------------+--------------------------+------------+----------+----------+----------+----------+
| digest | SUBSTR(digest_text,0,25) | count_star | sum_time | avg_time | min_time | max_time |
+--------------------+--------------------------+------------+----------+----------+----------+----------+
| 0x4ac6cc3e8e66e2a5 | SELECT DISTINCT c FROM s | 933 | 3502143 | 3753 | 792 | 24209 |
| 0x44bcb144058686eb | SELECT DISTINCT c FROM s | 940 | 3711176 | 3948 | 695 | 23823 |
| 0xac80a5ea0101522e | SELECT c FROM sbtest1 WH | 974 | 3518589 | 3612 | 810 | 23187 |
| 0x250cb4007721d69 | SELECT c FROM sbtest3 WH | 9584 | 12767018 | 1332 | 384 | 22605 |
| 0xc19480748ae79b4b | SELECT DISTINCT c FROM s | 937 | 3783683 | 4038 | 1004 | 21315 |
+--------------------+--------------------------+------------+----------+----------+----------+----------+
#查找按照总执行时间排序的前5个查询,平均执行时间至少为1秒,并且显示占总执行时间的百分比
ProxyQL-Admin> 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;
#查找按总执行时间排序的前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;
通过上面查询stats_mysql_query_digest表,对数据进行分析,我们可能需要将某些SQL路由到从库执行查询。
#将sun_time执行时间最长的SQL路由到hostgroup_id=2(从库)
ProxyQL-Admin> insert into mysql_query_rules (rule_id,active,digest,destination_hostgroup,apply) values (1,1,'0x250cb4007721d69',2,1);
ProxyQL-Admin> load mysql query rules to runtime;
ProxyQL-Admin> save mysql query rules to disk;
ProxyQL-Admin> select * from stats.stats_mysql_query_digest_reset;
#sysbench进行测试
sysbench /usr/local/share/sysbench/oltp_point_select.lua --report-interval=5 --threads=4 --max-time=60 --mysql-user='stnduser' --mysql-password='stnduser' --mysql-host=192.168.1.100 --mysql-port=6033 --table_size=100000 --tables=3 run
#查询stats_mysql_query_digest表,我们发现0x250cb4007721d69已经被路由到了hg2了
ProxyQL-Admin> SELECT hostgroup hg, sum_time, count_star, digest_text FROM stats.stats_mysql_query_digest ORDER BY sum_time DESC limit 5;
+----+----------+------------+----------------------------------+
| hg | sum_time | count_star | digest_text |
+----+----------+------------+----------------------------------+
| 1 | 49633532 | 56717 | SELECT c FROM sbtest1 WHERE id=? |
| 1 | 48987262 | 56178 | SELECT c FROM sbtest2 WHERE id=? |
| 2 | 42845618 | 56898 | SELECT c FROM sbtest3 WHERE id=? |
+----+----------+------------+----------------------------------+
最后,确保在应用更改后重新评估工作负载,因为它肯定会发生变化,您可能会发现可以继续优化的新查询。这里描述的查询分析方法应该是一个持续的过程,以确保您可以从ProxySQL部署中获得最大的价值