当谈到ProxySQL与客户端的好处和用例时,我通常引用的一个特性是查询重写引擎。这是一个很好的特性,经常用于分片(我曾经在在MySQL水平缩放-分片后续).我引用的另一个用例是“临时应用程序修复”。虽然这绝对是一个有效的用例,但我个人还没有遇到过应用程序修复不是微不足道的问题。
最近,一个客户端遇到了这样的情况:pt-archiver无法对主键中包含位列的表中的行进行归档。这当然是一个边缘情况,但我们希望修复是微不足道的。不幸的是,问题的根源在于Perl DBI库在默认情况下引用和处理位数据类型的方式。
当执行查询时,Perl试图引用一个空字符串而不是位表示0,导致工具失败(注意,这是来自本地复制的虚拟模式/数据的输出):
|
1
2
3.
|
2022-10-18 t14
:
19
:
02
0
0
DBD
:
:
mysql
:
:
圣
执行
失败的
:
截断
不正确的
双
价值
:
”
[
为
声明
“DELETE FROM myd_test”。`杰拉尔德`在哪里(`id`=?AND ' val ' = ? "
与
ParamValues
:
0=2
,
1=“。”
]
在
/usr/箱子/pt-存储服务器
行
6795.
2022-10-18 t14
:
19
:
02.698906 z
3001
查询
删除
从
`
myd_test
`
.
`
杰拉尔德
`
在哪里
(
`
id
`
=
' 2 '
和
`
瓦尔
`
=
”
)
|
的Bug被报告,工程人员开始着手修复,但表仍然在增长,需要迅速清除(以非锁定的方式)。
查看查询,我们可以识别出一个简单的围绕位列的CAST已经实现了我们在这种边缘情况下所寻找的结果(因为bit(1)不是0就是1)。不幸的是,MySQL运行的版本没有重写DML查询的能力(这是在8.0.12中引入的:https://dev.mysql.com/doc/refman/8.0/en/rewriter-query-rewrite-plugin.html).最后,在应用程序修复不是微不足道的情况下,需要在ProxySQL中的查询重写引擎来解决一个立即的问题!
为了快速设置环境,在运行pt-archiver的主机上本地安装了ProxySQL,并使用单个后端(目标测试床服务器)进行设置。使用此设置,您只需将pt-archiver连接到本地主机,并允许查询重写通过ProxySQL流向后端服务器。请注意-在这个设置中没有任何复杂或特殊的操作-只是一个主机组中的一个服务器后端。
一旦ProxySQL启动并运行,我就运行pt-archiver,等待它失败,然后检查stats_mysql_query_digest表中记录的查询摘要id。下面是我的测试床的主要查询和相关的摘要散列:
- 获取第一块:0 x0025b6a9e5f76e31
1选择 SQL_NO_CACHE ` id ` , ` 瓦尔 ` 从 ` 测验 ` . ` 杰拉尔德 ` 力 指数 ( ` 主要的 ` ) 在哪里 ( ( 瓦尔 ) 在 ( 选择 一个 .val 从 测验 .gerald 一个 在哪里 id > ? ) ) 订单 通过 ` id ` , ` 瓦尔 ` 限制 ? - 下一段:0 x3128ed8c7a53f401
1选择 SQL_NO_CACHE ` id ` , ` 瓦尔 ` 从 ` 测验 ` . ` 杰拉尔德 ` 力 指数 ( ` 主要的 ` ) 在哪里 ( ( 瓦尔 ) 在 ( 选择 一个 .val 从 测验 .gerald 一个 在哪里 id > ? ) ) 和 ( ( ` id ` > ? ) 或 ( ` id ` = ? 和 ` 瓦尔 ` >= ? ) ) 订单 通过 ` id ` , ` 瓦尔 ` 限制 ? - 删除块:0 x3ce028a9657e611f
1删除 从 ` 测验 ` . ` 杰拉尔德 ` 在哪里 ( ` id ` = ? 和 ` 瓦尔 ` = ? )
使用每个摘要哈希,然后我添加了三个查询重写规则,将位列转换为unsigned int,如下所示:
|
1
2
3.
4
5
6
7
8
|
插入
成
mysql_query_rules
(
rule_id
,
活跃的
,
消化
,
match_pattern
,
replace_pattern
,
应用
)
值
(
125
,
1
,
“0 x0025b6a9e5f76e31”
,
“id”、“val”从“
,
' id ',cast(' val ' as unsigned) as ' val ' FROM"
,
1
)
;
插入
成
mysql_query_rules
(
rule_id
,
活跃的
,
消化
,
match_pattern
,
replace_pattern
,
应用
)
值
(
126
,
1
,
“0 x3128ed8c7a53f401”
,
“id”、“val”从“
,
' id ',cast(' val ' as unsigned) as ' val ' FROM"
,
1
)
;
插入
成
mysql_query_rules
(
rule_id
,
活跃的
,
消化
,
match_pattern
,
replace_pattern
,
应用
)
值
(
127
,
1
,
“0 x3ce028a9657e611f”
,
”和“val””
,
"AND cast(' val ' as unsigned)"
,
1
)
;
|
注意这里的关键列——match_pattern和replace_pattern。在这里,我们可以动态重写查询中有问题的部分。对于delete块查询表单,我们重写了delete查询,看起来像这样:
|
1
|
删除
从
`
测验
`
.
`
杰拉尔德
`
在哪里
(
`
id
`
=
?
和
投
(
`
瓦尔
`
作为
无符号
)
=
?
)
|
有了新规则后,通过本地ProxySQL重新运行pt-archiver可以正确地清理表!虽然这不是一个长期的解决方案(和Pt-archiver修复已经发布),它展示了一个使用ProxySQL修复无法及时更新的应用程序的真实示例。
雷竞技下载官网Percona Distribution for MySQL是最完整、稳定、可扩展和安全的开源MySQL解决方案,为您最关键的业务应用程序提供企业级数据库环境……而且它是免费使用的!






A few years ago a HW vendor changed its serial number scheme from all numbers to HEX based, so the nice but old monitoring tool (same vendor was not able to add such a serial number.
由于工具是固定的主机/端口,我们将MySQL移动到不同的端口,安装proxysql监听3306,并将所有流量重定向到MySQL。
在第二步中,我们将列数据类型从数字更改为字符,以便能够接受新的序列号格式。
由于字符串需要“围绕它们”,我们生成了一个重写规则INSERT到那个表中,以添加“围绕值”。
监视工具所做的所有其他事情都工作得很好,只是添加了一个新盒子raybet雷竞技竞猜在线官网(其基于HEX的序列号)需要这个工作。