【原创】MySQL Proxy - read_query_result()

       read_query_result() 函数仅在你之前手动向 query 队列中添加了 query 的情况下,有结果集从服务器端返回的时候被调用。如果你没有对 query 队列进行过操作,该函数不会被调用。该函数仅具有一个入参,即结果包(在 Lua 脚本中可以认为该包对应的是 Injection 结构),其中包含了一系列属性: 

  • id: 结果集 ID ,其对应于 当 query 包被客户端向服务器提交时使用 append(id) 函数对 query 队列操作时设置的 ID 值。你必须设置 resultset_is_needed 标志,以便当拦截到来自于服务器的返回结果集时,进行相应处理,之后再返回给客户端。参阅 proxy.queries 。
  • query: 原始 query 的文本内容。
  • query_time: 从 query 被发送到服务器,到接收到结果集的第一行时,所需要的微秒数。
  • response_time: 从 query 被发送到服务器,到接收到结果集的最后一行时,所需要的微秒数。
  • resultset: 结果集数据的内容。

       通过对来自 MySQL 服务器的返回结果信息的分析处理,可以提取出与你之前注入的 query 语句匹配的结果,并返回修改后的结果集(例如返回一个经过修改的 query 产生的结果),甚至创建属于你自己的结果集。 

       下面的 Lua 脚本,将输出每一个发送到服务器的 query 对应的文本内容,以及 query 时间和 response 时间(即开始执行 query 的时刻和返回该 query 结果的时刻): 

function read_query( packet )
        if packet:byte() == proxy.COM_QUERY then
                print("we got a normal query: " .. packet:sub(2))

                proxy.queries:append(1, packet )

                return proxy.PROXY_SEND_QUERY
        end
end

function read_query_result(inj)
        print("query-time: " .. (inj.query_time / 1000) .. "ms")
        print("response-time: " .. (inj.response_time / 1000) .. "ms")
end

       你可以通过 read_query_result() 函数获得返回结果中的 resultset 属性的 row 属性。例如,你可以使用下面的 Lua 代码段来递归显示返回结果中所有行的第一列内容: 

for row in inj.resultset.rows do
        print("injected query returned: " .. row[1])
end

       正如 read_query() 函数一样,read_query_result() 函数能够根据返回结果的内容,按需返回结果的不同值。例如,如果你之前注入了额外的 query 到 query 队列中,然后在获取返回的结果集后,移除与额外 query 对应的结果,仅返回与客户端发送的原始 query 对应的结果。 

       下面的例子注入额外的 SELECT NOW() 语句到 query 队列中,并设置了一个与原始 query 不同的 ID 值。在 read_query_result() 函数中,如果发现了与我们自己注入的 query 的 ID 相匹配的结果,我们将显示结果的行内容,然后通过 return proxy.PROXY_IGNORE_RESULT 语句使该结果不会被返回给客户端。如果结果是由任何其他 query 产生,则打印出 query 相应的时间信息,并返回默认值,即返回不做任何修改的结果集给客户端。我们同样可以显式地使用 return proxy.PROXY_IGNORE_RESULT 来将结果返回给 MySQL 客户端。 

function read_query( packet )
        if packet:byte() == proxy.COM_QUERY then
                proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()", {resultset_is_needed = true} )
                proxy.queries:append(1, packet, {resultset_is_needed = true})
                proxy.queries:append(2, string.char(proxy.COM_QUERY) .. "SELECT NOW()", {resultset_is_needed = true} )

                return proxy.PROXY_SEND_QUERY
        end
end

function read_query_result(inj)
        if inj.id == 2 then
                for row in inj.resultset.rows do
                        print("injected query returned: " .. row[1])
                end
                return proxy.PROXY_IGNORE_RESULT
        else
                print("query-time: " .. (inj.query_time / 1000) .. "ms")
                print("response-time: " .. (inj.response_time / 1000) .. "ms")
        end
end
时间: 2025-01-20 13:29:20

【原创】MySQL Proxy - read_query_result()的相关文章

【原创】MySQL Proxy - 内部结构

        在 MySQL Proxy 的脚本元素中有一些基本的内部结构需要知道.其中最主要的结构就是 proxy ,其提供了访问贯穿脚本中的许多公共结构的接口,例如连接列表和配置的 backend server .其他结构,例如来自客户端的包和返回的结果集等,只有在具体的脚本函数的上下文环境中才是可以访问的.  下表中描述了 MySQL proxy 脚本元素的公共属性.  Attribute Description connection A structure containing the

【原创】MySQL Proxy - query注入动作中的脚本序列

    下图展示了一个如何使用 proxy 将客户端发送过来的 query 注入到 query 队列的例子.因为 proxy 位于客户端和 MySQL 服务器之间,所以经由 proxy 发送到服务器,以及由 proxy 最终返回给客户端的信息,不需要做到完全匹配或者关联.一旦客户端连接到了 proxy ,下图中展现的由客户端发送每一个单独的 query 引起的命令序列将会发生.           当客户端向 proxy 提交了一个 query 的时候,proxy 内部的 read_query(

【原创】MySQL Proxy - 脚本

       你可以通过使用嵌入式 Lua 脚本语言对 MySQL Proxy 的行为进行控制,以使得其能够对发送给 MySQL 服务器的 query 和 response 进行操纵.  下图展现了 MySQL Proxy 中使用的类的总览.           在 MySQL Proxy 和服务器之间的主要交互功能是通过 Lua 脚本定义的一个或者多个函数.根据客户端与一个或者多个 backend MySQL servers 之间通信序列中不同的事件和操作,定义如下一些关键函数:  conne

【原创】MySQL Proxy中socketpair的使用

      学习 MySQL Proxy 0.8.3 的源码后可知,其全部事件处理线程均对全局 socketpair 的读端进行了监听,以实现通知管道的功能:threads->event_notify_fds[0] .  ? 1 2 3 4 5 6 7 8 9 10 11 12 13 int chassis_event_threads_init_thread(chassis_event_threads_t *threads, chassis_event_thread_t *event_threa

【原创】MySQL Proxy - 底层实现篇

底层实现篇(chassis)     [ Configfile and Commandline Options]           glib2 提供了 config-file 解析和 command-line option 解析功能. 其提供了将 option 以相同方式暴露给调用者的方法,以及从 Configfile 和 Commandline 获取 option 的功能.    所有 option 的解析过程都可以分为三步: 1. 提取   command-line 上的 basic op

【原创】MySQL Proxy - 核心篇

核心层篇(Core)          Network Core 构建于 socket 处理实现的基础之上,将 client connection 和 server connection 关联到一起.     [Connection Life Cycle]    connection 可处于下面 4 种协议基本 phase 之一:    connect authentification query disconnect        通过对 plugin 功能的定制实现,可以改变 network

原创】MySQL Proxy - 架构篇

架构篇(architecture)         MySQL Proxy 的定位是存在于 mysql client 和 mysql server 之间的一个简单的程序,能够对从其上通过的数据进行检查.转换和直接进行相应操作.  应用范围包括:  负载均衡(load balancing) 故障处理(fail over) 查询追踪(query tracking) 查询分析(query analysis) (...)        内部实现上讲,MySQL Proxy 是这样的一个协议栈:  (应该

【原创】MySQL Proxy - 使用

       存在许多种使用 MySQL Proxy 的不同方法.采用最基本用法,你可以允许 MySQL Proxy 将来自客户端的 query 透传到后端的一个服务器.如果打算让 MySQL Proxy 在这种模式下工作,你只需要在命令行上指定 proxy 打算连接的 backend server 的信息:  ? 1 shell> mysql-proxy --proxy-backend-addresses=sakila:3306        如果你指定了多个后端 MySQL 服务器,prox

【原创】MySQL Proxy - 概况

       MySQL Proxy 是一种在网络上使用 MySQL 网络协议进行通信的应用,提供了一或多个 MySQL server 与一或多个 MySQL client 之间的通信功能.由于 MySQL Proxy 使用的是 MySQL 网络协议,故其可以在不做任何修改的情况下,配合任何符合该协议的且与 MySQL 兼容的客户端一起使用.这其中也包括 MySQL 的命令行客户端,任何使用了 MySQL 客户端库的客户端,以及任何支持 MySQL 网络协议的连接器(connector).