暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

[译文] MySQL:绑定 ORM

原创 Kristian KÖHNTOPP 2021-09-23
305

我的任务是收集有关单个查询的性能数据,PERFORMANCE_SCHEMA在 MySQL 中使用(简称 P_S),将其发送到其他地方以与其他数据集成。

在更宏大的计划中,我需要定义我真正感兴趣的查询中的哪些性能数据。我还需要找到一种方法将查询(如在服务器上看到的)归因于代码库中的某个点客户端,这在使用 ORM 或其他 SQL 生成器时并不总是那么容易。最后我需要找到一种方法来查看客户端代码执行上下文中的查询执行情况,因为数据访问只是系统性能的一部分。

这是关于标记一个查询,以便它可以在源中识别并归因于它在代码库中的来源。

在我的场景中,我可以控制 ORM 或 DAO。我可以查看堆栈帧,识别execute函数的调用者并将文件名和行号或其他识别信息放入生成的查询文本中。我还可以从调用者那里获取标识符(“跟踪 ID ”)并将它们传递下去,因此查询执行可以是生成 SQL 并运行它的 ORM 调用的子跨度。

什么会起作用?

评论从 P_S 中删除

让我们先尝试评论。该手册知道3种在MySQL评论:

  • /* … */ 类似C的评论。
  • … 壳类评论。

  • – … 不太像 SQL 的注释。

通过保留注释,我可以将识别信息放入查询字符串中,然后从 P_S 中提取它。我可以使用此信息来确定查询的属性并将其链接到代码中的来源。

在一个连接中,我发出

mysql [localhost:8025] {msandbox} (kris) > select /* keks */ * from t;m t; ... 8192 rows in set (0.00 sec)
复制

结果集无关紧要,但我/* … */在查询字符串中添加了注释。

在 P_S 中,我发现

mysql [localhost:8025] {msandbox} (performance_schema) > select sql_text from events_statements_history where thread_id = 47 order by event_id desc limit 1; +------------------+ | sql_text | +------------------+ | select * from t | +------------------+ 1 row in set (0.00 sec)
复制

评论已被剥离,您仍然可以看到双空格。

老式的 SQL 注释和 shell 注释似乎已经在客户端中消失了:

mysql [localhost:8025] {msandbox} (kris) > select -- keks -> * from t limit 3; ... 3 rows in set (0.00 sec) mysql [localhost:8025] {msandbox} (kris) > <cursor up> mysql [localhost:8025] {msandbox} (kris) > select * from t limit 3;
复制

壳牌评论也会发生同样的情况:当然,同样,评论不在 P_S 中。

目前还不清楚为什么评论被删除,以及在哪里删除。可能是作为前置阶段安装到后期查询缓存的语句条件化留下的痕迹,祝福它腐烂的灵魂。

好像有两种机制,一种用于SQL和Shell注释,一种用于C注释:查看客户端历史时,编辑器没有记住Shell和SQL注释,但C注释是。

这种处理上的差异是有道理的,因为 MySQL 使用魔术 C 注释来控制语句解析以实现兼容性:SELECT /*! 80000 NEW_KEYWORD */被SELECTMySQL 8.0.0 之前的版本和SELECT NEW_KEYWORDMySQL 8.0.0 及更高版本解析为 a 。这允许mysqldump和其他程序发出 SQL 代码,在旧版本的 MySQL 上优雅地降级。

类似的语法,/+ …/用于控制优化器提示。

新增:查询属性

查询属性是一个新奇事物(8.0.23 或更新版本),它允许客户端对查询进行注释。注释保存在服务器中,并在某些上下文中可用,但它们什么也不做。

手册解释了这一点:

  • 在发送语句之前定义属性。
  • 它们一直存在到语句结束。
  • 当它们存在时,可以在服务器端访问它们。

给出的示例正是我的用例:将识别信息从客户端传输到服务器,或者将插件的控制信息从客户端注入服务器以影响服务器中的查询处理。

查询属性在服务器中什么都不做。服务器不看他们。

C-API 客户端和 MySQL 命令行客户端支持查询属性。其他地方还没有太多支持。

检查功能的基本练习有效:

mysql [localhost:8025] {msandbox} (mysql) > INSTALL COMPONENT "file://component_query_attributes"; ... mysql [localhost:8025] {msandbox} (mysql) > query_attributes n1 v2 n2 v3 mysql [localhost:8025] {msandbox} (mysql) > select -> mysql_query_attribute_string('n1') AS 'attr 1', -> mysql_query_attribute_string('n2') AS 'attr 2', -> mysql_query_attribute_string('n3') AS 'attr 3'; +--------+--------+--------+ | attr 1 | attr 2 | attr 3 | +--------+--------+--------+ | v2 | v3 | NULL | +--------+--------+--------+ 1 row in set (0.00 sec)
复制

插件组件也在以下内存映射中可见mysqld:

kris@server:~$ grep query_attr /proc/94982/maps 7f7590f5b000-7f7590f5c000 r--p 00000000 fd:00 221893305 /home/kris/opt/mysql/8.0.25/lib/plugin/component_query_attributes.so 7f7590f5c000-7f7590f5d000 r-xp 00001000 fd:00 221893305 /home/kris/opt/mysql/8.0.25/lib/plugin/component_query_attributes.so 7f7590f5d000-7f7590f5e000 r--p 00002000 fd:00 221893305 /home/kris/opt/mysql/8.0.25/lib/plugin/component_query_attributes.so 7f7590f5e000-7f7590f5f000 r--p 00002000 fd:00 221893305 /home/kris/opt/mysql/8.0.25/lib/plugin/component_query_attributes.so 7f7590f5f000-7f7590f60000 rw-p 00003000 fd:00 221893305 /home/kris/opt/mysql/8.0.25/lib/plugin/component_query_attributes.so
复制

然后去哪儿?

我可以在我控制的客户端中生成查询,并使用识别信息对查询进行注释。在我的情况下,这些信息将是

  • 跟踪标志。如果要跟踪查询,则将出现跟踪标志。detault 是:查询将不会被跟踪。
  • 一组三个标识符(字母数字字符串:sha256 MAC、UUID 或表示整数的字符串)。它们是根 ID、父 ID 和查询 ID。这些标识符允许在更大的跟踪上下文中对跨度/父跨度关系进行建模。

我需要在服务器中找到一个插件的钩子。该插件必须在查询执行后运行,但执行计划、查询字符串和查询的 P_S 数据仍然存在。我对此还不熟悉,需要检查当前服务器上提供的内容。也许审计插件使用的钩子可以重新利用。

如果设置了跟踪标志,则需要访问

  • 查询属性
  • 如果可能,运行的查询计划(需要检查是什么EXPLAIN FOR CONNECTION)
  • 可以从 P_S 数据中收集的有关查询执行的信息

它需要将此信息转换为单个序列化形式,例如 JSON 字符串,然后以不阻塞服务器的方式将其导出。

过去在我的环境中执行此操作的通用方法是向本地主机发送 UDP 数据包。UDP 到 localhost 被认为是无损的,限制为 64K,如果侦听器不存在则丢弃数据。如果存在旋转/截断机制,则写入仅附加文件的文件也可以写入。

然后,我需要在我的客户端中获取 JSON,对其进行更多转换并将其发送给跟踪使用者,例如 Jaeger、Lightstep 或在我的情况下是 Honeycomb。

跟踪数据将在那里与来自其他组件的跨度连接,包括围绕生成 SQL 的 ORM 和调用到 ORM 的代码的跨度。这将允许查看查询的上下文,而无需对其进行 grep,使用现代 Web 工具分析生成它的上下文中的查询执行,并且通常将 SQL 调试与其他应用程序调试统一起来。

这使得对专门的“数据库性能监控”(DPM) 软件的需求消失了,至少对于个人开发人员而言是这样。DPM 仍然可以用于操作任务,但这些通常由电报 MySQL 收集器、Prometheus 和 Grafana 提供服务(这些通常比 DPM 更好)。

原文地址:https://blog.koehntopp.info/2021/09/16/binding-the-orm.html

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论