转载自:https://www.jianshu.com/p/597b840bf70c

(使用正则表达式实现基本的读/写分离)
在这一部分,我将通过一个示例来演示如何通过正则表达式来实现读/写分离。
首先,我们需要将之前创建的查询规则删除:
DELETE FROM mysql_query_rules; 然后,为读/写分别创建对应的基本规则:
UPDATE mysql_users SET default_hostgroup=10; # 所有的查询将默认路由到 HG10
LOAD MYSQL USERS TO RUNTIME;
SAVE MYSQL USERS TO DISK; # 如果想要将配置持久化保存到磁盘,就执行该语句
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply)
VALUES
(1,1,'^SELECT.*FOR UPDATE$',10,1),
(2,1,'^SELECT',20,1);
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK; # 如果想要将配置持久化保存到磁盘,就执行该语句 现在,将按照如下规则对查询语句进行路由: 所有SELECT FOR UPDATE语句将路由给HG10。
其它所有的SELECT语句都将路由给HG20。
其它所有查询也都将路由给HG10(这是默认主机组)
注意,我并不认为上面的读/写分离规则是多好的方法。我经常使用这个例子来描述如何配置规则,但它经常被误解为配置读/写分离的方式 。稍后我将演示更好的读/写方法。
现在,将上面的规则全部移除: DELETE FROM mysql_query_rules;
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK; # 如果想将配置持久化到磁盘,执行该语句
read/write split using regex and digest (使用正则表达式和digest配置读写分离)
有效地设置读/写分离的配置过程如下: 首先配置ProxySQL,让所有的请求都发送给单个MySQL节点master(既读又写)
检查stats_mysql_query_digest表中开销最大的SELECT语句
然后决定这些大开销的语句中哪些允许路由给负责读的节点
然后配置mysql_query_rules表(创建规则),将大开销的SELECT语句路由给读组
这个方案的本质非常简答:只发送那些想要发送给slaves/readers的查询,而不仅仅通过SELECT语句来判断。 Find expensive queries using stats_mysql_query_digest (从stats_mysql_query_digest表中找出开销较大的查询语句)
这里给出了几个示例,用来解释如何找出哪些应该路由给读组的潜在查询。
由于ProxySQL将所有的统计数据和指标都导出到了各种表中,因此可以根据这些表创建复杂的查询来收集想要的信息。
下面是在一个非常繁忙的ProxySQL实例下收集的数据,这个实例已经持续运行了几个月,处理的数据有上千亿。 首先查找出总执行时间排在前5的查询: 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 |
+--------------------+--------------------------+------------+---------------+
| 0x037C3E6D996DAFE2 | SELECT a.ip_id as ip_id, | 2030026798 | 1479082636017 |
| 0xB081A85245DEA5B7 | SELECT a.ip_id as ip_id, | 2025902778 | 1206116187539 |
| 0x38BE36BDFFDBE638 | SELECT instance.name as | 59343662 | 1096236803754 |
| 0xB4233552504E43B8 | SELECT ir.type as type, | 1362897166 | 488971769571 |
| 0x4A131A16DCFFD6C6 | SELECT i.id as id, i.sta | 934402293 | 475253770301 |
+--------------------+--------------------------+------------+---------------+
5 rows in set (0.01 sec) 再找出执行次数排在前5的查询: 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 LIMIT 5;
+--------------------+--------------------------+------------+---------------+
| digest | SUBSTR(digest_text,0,25) | count_star | sum_time |
+--------------------+--------------------------+------------+---------------+
| 0x037C3E6D996DAFE2 | SELECT a.ip_id as ip_id, | 2030040688 | 1479092529369 |
| 0xB081A85245DEA5B7 | SELECT a.ip_id as ip_id, | 2025916528 | 1206123010791 |
| 0x22E0A5C585C53EAD | SELECT id as instanceid, | 1551361254 | 426419508609 |
| 0x3DB4B9FA4B2CB36F | SELECT i.id as instancei | 1465274289 | 415565419867 |
| 0xB4233552504E43B8 | SELECT ir.type as type, | 1362906755 | 488974931108 |
+--------------------+--------------------------+------------+---------------+
5 rows in set (0.00 sec) 这些查询可以被缓存吗?ProxySQL的查询缓存可以实现该功能。 找出最长执行时间排在前5的查询(译注:每个查询都有最长执行时间max_time和最短执行时间min_time): 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 |
+--------------------+--------------------------+------------+--------------+----------+----------+-----------+
| 0x36CE5295726DB5B4 | SELECT COUNT(*) as total | 146390 | 185951894994 | 1270249 | 445 | 237344243 |
| 0xDA8C56B5644C0822 | SELECT COUNT(*) as total | 44130 | 24842335265 | 562935 | 494 | 231395575 |
| 0x8C1B0405E1AAB9DB | SELECT COUNT(*) as total | 1194 | 1356742749 | 1136300 | 624 | 216677507 |
| 0x6C03197B4A2C34BE | Select *, DateDiff(Date_ | 4796 | 748804483 | 156131 | 607 | 197881845 |
| 0x1DEFCE9DEF3BDF87 | SELECT DISTINCT i.extid | 592196 | 40209254260 | 67898 | 416 | 118055372 |
+--------------------+--------------------------+------------+--------------+----------+----------+-----------+
5 rows in set (0.01 sec) 这个具体的结果表明,一些查询具有非常高的最大执行时间,而最短执行时间却非常小,并且平均执行速度也相当慢。
例如,digest值为0x36CE5295726DB5B4的查询,平均执行时间为1.27秒,但最小执行时间才0.4毫秒,最大时间久到了237.34秒。对于这样的查询,也许有必要研究一下为什么执行时间不均匀。 找出总执行时间排在前5,且最短执行时间至少为1毫秒的查询: Admin> 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;
+--------------------+--------------------------+------------+-------------+----------+----------+----------+
| digest | SUBSTR(digest_text,0,20) | count_star | sum_time | avg_time | min_time | max_time |
+--------------------+--------------------------+------------+-------------+----------+----------+----------+
| 0x9EED412C6E63E477 | SELECT a.id as acco | 961733 | 24115349801 | 25074 | 10994 | 7046628 |
| 0x8DDD43A9EA37750D | Select ( Coalesce(( | 107069 | 3156179256 | 29477 | 1069 | 24600674 |
| 0x9EED412C6E63E477 | SELECT a.id as acco | 91996 | 1883354396 | 20472 | 10095 | 497877 |
| 0x08B23A268C35C08E | SELECT id as reward | 49401 | 244088592 | 4940 | 1237 | 1483791 |
| 0x437C846F935344F8 | SELECT Distinct i.e | 164 | 163873101 | 999226 | 1383 | 7905811 |
+--------------------+--------------------------+------------+-------------+----------+----------+----------+
5 rows in set (0.01 sec) 找出总执行时间排在前5,且平均执行时间至少为1秒的查询。同时输出每个查询的总时间占所有查询总时间的百分比: 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;
+--------------------+--------------------------+------------+--------------+----------+-------+
| digest | SUBSTR(digest_text,0,25) | count_star | sum_time | avg_time | pct |
+--------------------+--------------------------+------------+--------------+----------+-------+
| 0x36CE5295726DB5B4 | SELECT COUNT(*) as total | 146390 | 185951894994 | 1270249 | 2.11 |
| 0xD38895B4F4D2A4B3 | SELECT instance.name as | 9783 | 12409642528 | 1268490 | 0.141 |
| 0x8C1B0405E1AAB9DB | SELECT COUNT(*) as total | 1194 | 1356742749 | 1136300 | 0.015 |
+--------------------+--------------------------+------------+--------------+----------+-------+
3 rows in set (0.00 sec) 找出总执行时间排在前5,且平均执行时间至少为15毫秒的查询。同时输出每个查询的总时间占所有查询总时间的百分比: 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 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;
+--------------------+--------------------------+------------+---------------+----------+--------+
| digest | SUBSTR(digest_text,0,25) | count_star | sum_time | avg_time | pct |
+--------------------+--------------------------+------------+---------------+----------+--------+
| 0x38BE36BDFFDBE638 | SELECT instance.name as | 59360371 | 1096562204931 | 18472 | 13.006 |
| 0x36CE5295726DB5B4 | SELECT COUNT(*) as total | 146390 | 185951894994 | 1270249 | 2.205 |
| 0x1DEFCE9DEF3BDF87 | SELECT DISTINCT i.extid | 592281 | 40215136635 | 67898 | 0.477 |
| 0xDA8C56B5644C0822 | SELECT COUNT(*) as total | 44130 | 24842335265 | 562935 | 0.295 |
| 0x9EED412C6E63E477 | SELECT a.id as accountid | 961768 | 24116011513 | 25074 | 0.286 |
+--------------------+--------------------------+------------+---------------+----------+--------+
5 rows in set (0.00 sec) 难道所有这些查询都应用路由到master上去执行吗?如果一个查询的平均执行时间在1秒以上,那么答案可能是no。对于某些非常繁忙且对性能要求较高的应用程序,甚至可以考虑将平均执行时间在15毫秒的查询路由给slave。
例如,我们可以决定将digest=0x38BE36BDFFDBE638的查询路由给slave:
INSERT INTO mysql_query_rules (rule_id,active,digest,destination_hostgroup,apply)
VALUES(1,1,'0x38BE36BDFFDBE638',20,1); 类似地,在检查了如下语句的输出后:
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(*)开头的语句路由给slave:
INSERT INTO mysql_query_rules (rule_id,active,match_digest,destination_hostgroup,apply)
VALUES(1,1,'^SELECT COUNT\(\*\)',20,1); 最后,将配置加载到RUNTIME,并将它持久化保存到磁盘数据库中。
LOAD MYSQL QUERY RULES TO RUNTIME;
SAVE MYSQL QUERY RULES TO DISK;
Conclusion (结论:)
ProxySQL可以非常有效、非常弹性地对各种查询进行选择性地路由。
虽然对于某些应用程序来说,将所有SELECT语句路由给slaves/readers,其余都路由给writers/masters是可以接受的,但对于很多应用程序来说,其实并没这么简单。作为DBA,应当具备"使用复杂的规则配置ProxySQL,只将那些不应该路由给master的查询路由给slaves,而不需要更改任何应用程序"的能力。

ProxySQL 读写分离方法的更多相关文章

  1. MySQL ProxySQL读写分离实践

    目的 在上一篇文章MySQL ProxySQL读写分离使用初探里初步介绍了ProxySQL的使用,本文继续介绍它的一些特点和DBProxy的性能差异.深入一些去了解ProxySQL,通过测试来说明Pr ...

  2. mysqlfailover高可用与proxysql读写分离配置

    proxysql官方推荐两种高可用方案: 1.MHA+proxysql 2.mysqlrpladmin+proxysql MySQLfailover工具包含在mysqlrpladmin工具中,所以两者 ...

  3. MHA+ProxySQL 读写分离高可用

    文档结构如下: 1.ProxySQL说明 ProxySQL是mysql的一款中间件的产品,是灵活的mysql代理层,可以实现读写分离,支持query路由器的功能,支持动态指定sql进行缓存,支持动态加 ...

  4. MySQL ProxySQL读写分离使用初探

    目的 在美团点评DBProxy读写分离使用说明文章中已经说明了使用目的,本文介绍ProxySQL的使用方法以及和DBProxy的性能差异.具体的介绍可以看官网的相关说明,并且这个中间件也是percon ...

  5. ProxySQL 读写分离实践

    前言 ProxySQL是一个高性能的MySQL中间件,拥有强大的规则引擎.具有以下特性: 连接池,而且是 multiplexing 主机和用户的最大连接数限制 自动下线后端DB 延迟超过阀值 ping ...

  6. Proxysql读写分离配置

    ProxySQL是Percona主推的读写分离中间件,下载地址为: https://www.percona.com/downloads/proxysql/ 一.安装 1:下载 wget https:/ ...

  7. ProxySQL读写分离

    我们首先看一下自己的环境: MHA已经搭建: master: slave: slave: MHA manager在172.16.16.34,配置文件如下: [root@localhost bin]# ...

  8. ProxySQL读写分离代理

    实现ProxySQL反向代理Mysql读写分离 简介 ProxySQL相当于小型的数据库,在磁盘上有存放数据库的目录:ProxySQL用法和mysql相似 启动ProxySQL后会有两个监听端口: 6 ...

  9. ProxySQL读写分离测试(续)

      Preface       I've implemented ProxySQL on PXC yesterday but got some errors when configured query ...

随机推荐

  1. paddlespeech asr 使用教程

    目录 安装 paddle框架安装 软件源安装 源码安装 快速使用 下载测试使用的音频 非流式命令行接口(CLI) 非流式Server服务 流式Server服务 指令详解 打印paddlespeech_ ...

  2. 强化学习-学习笔记14 | 策略梯度中的 Baseline

    本篇笔记记录学习在 策略学习 中使用 Baseline,这样可以降低方差,让收敛更快. 14. 策略学习中的 Baseline 14.1 Baseline 推导 在策略学习中,我们使用策略网络 \(\ ...

  3. java的类

    public class demo01 { public static void main(String[] args) { //类名可用中文也可用英文,但是不建议用中文 String 王者荣耀=&q ...

  4. 关于ios的IDFA

    了解IDFA,看我这篇文章就够了双11剁手后,我静静的限制了广告追踪 今年双11爆了,据统计,全天交易额1207亿,移动端占比82%,在马云的持续教育和移动端的爆发下,用户在移动端消费的习惯已经不可逆 ...

  5. 第十四天python3 面向对象

    1.面向对象 是对现实世界中的事物进行抽象的方式: 一切皆对象: 对象是数据和操作的封装: 对象之间相互独立,但也可以相互作用: 三要素: 封装: 数据与方法的集合: 提供一个或者多个接口来访问:隐藏 ...

  6. TCP通信的概述

  7. Odoo14 需要哪些技术

    1 PostgreSQL:数据库,存储数据. 2 Python :主要作用是控制数据库,如:建表.关联字段.批量数据-- 3 html.css.javascript:基础前端. 4 scss:前端样式 ...

  8. SQL 注入复习总结

    一.介绍 1.什么是SQL注入? sql 注入是一种将 sql 代码添加到输入参数中,传递到 sql 服务器解析并执行的一种攻击手法. 2.SQL注入的原理 SQL 是操作数据库数据的结构化查询语言, ...

  9. 使用.NET简单实现一个Redis的高性能克隆版(七-完结)

    译者注 该原文是Ayende Rahien大佬业余自己在使用C# 和 .NET构建一个简单.高性能兼容Redis协议的数据库的经历. 首先这个"Redis"是非常简单的实现,但是他 ...

  10. transform: scale() 实现鼠标悬浮在元素之上出现和消失

    前言 transform属性允许你旋转,缩放,倾斜或平移给定元素.其中scale(x, y)就是实现元素缩放的属性值. scale(x, y)的 x 乘以原本元素的 x:y 乘以原本的元素 y,就可以 ...