【问题标题】:Unexpected SQL queries to Postgres database on Rails/Heroku在 Rails/Heroku 上对 Postgres 数据库的意外 SQL 查询
【发布时间】:2013-01-19 14:30:07
【问题描述】:

我正在使用 NewRelic 对我的一个 Rails 应用程序提出一个非常长的请求,并发现许多看起来完全陌生的 SQL 查询占用了相当长的时间。我已经用谷歌搜索了,但我对它们是什么一无所知,更不用说我是否能阻止它们的发生。

SELECT COUNT(*) FROM pg_class c LEFT JOIN pg_namespace n ON n.oid = c.relnamespace WHERE c.relkind in (?, ?) AND c.relname = ? AND n.nspname = ANY (current_schemas(false))

……和……

SELECT a.attname, format_type(a.atttypid, a.atttypmod), pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod FROM pg_attribute a LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum WHERE a.attrelid = ?::regclass AND a.attnum > ? AND NOT a.attisdropped ORDER BY a.attnum

…每次发生 7 次,总共耗时 145 毫秒和 135 毫秒(分别)。

SELECT DISTINCT(attr.attname) FROM pg_attribute attr INNER JOIN pg_depend dep ON attr.attrelid = dep.refobjid AND attr.attnum = dep.refobjsubid INNER JOIN pg_constraint cons ON attr.attrelid = cons.conrelid AND attr.attnum = cons.conkey[?] WHERE cons.contype = ? AND dep.refobjid = ?::regclass

…以 104ms 的成本执行了 2 次,并且…

SHOW search_path

…在一次调用中要求 45 毫秒。

我的直觉说这些与 Postgres Rails 适配器有关,但我不明白是什么触发了它们或它们在做什么,或者(更重要的是)为什么它们在典型请求期间被触发。


我刚刚更彻底地检查了日志,看起来运行此请求的 Dyno 已在几秒钟前转换为“up”,因此该请求很可能是第一个请求。

【问题讨论】:

    标签: sql ruby-on-rails postgresql heroku newrelic


    【解决方案1】:

    我在使用 Apartment Gem 与 Postgres Schema 进行多租户时收到这些查询。显然,每个 exclude_model - 一个使用默认模式的模型 - 在每个请求中都生成一个“pg_class”查询。

    Apartment 的人在 0.25.0 版本中修复了它。

    【讨论】:

      【解决方案2】:

      表 pg_class、pg_attribute、pg_depend 等都描述了 postgres 中的表、列和依赖项。在 Rails 中,模型类由表定义,因此 Rails 读取表和列以找出每个模型的属性。

      在开发模式下,它会在每次访问模型时查找这些值,因此如果您最近进行了更改,Rails 会知道。在生产模式下,Rails 会缓存这些内容,因此您看到这些内容的频率会大大降低,因此这真的不是问题。

      【讨论】:

      • 我以为 Rails 使用schema.rb 来确定数据库的结构,而不是检查数据库。
      • 不,schema.rb 是在部署时创建表的代码; Rails 不会解析这个来确定属性。相反,它会查看数据库中的表定义。
      • 我的意思是包含一个解释what schema.rb is for的链接
      • 我认为您在评论中指的是这个链接:guides.rubyonrails.org/…
      【解决方案3】:

      这些查询用于获取表和字段的“定义”,并且可能被框架用于在 Ruby 中自动生成模型和/或验证规则。 (例如“内省”)

      我确实没有对 Ruby 和您正在使用的框架有经验,但我不认为这些查询源自 SQL 注入。

      您可以自己在 pgAdmin 或 psql 中运行查询,以显示它们产生的结果并了解它们从数据库中获得了哪些信息

      【讨论】:

      • 谢谢——这就是我的怀疑,但我仍然不知道为什么它们会在这样的请求期间发生。
      • 通常框架会“缓存”这些结果,但如果您当前正在开发并启用了调试,则可能是在调试模式下禁用了缓存,因此它将为每个请求执行这些查询跨度>
      • 这是一个生产应用程序,但很可能这是对 Dyno 的第一个请求(刚刚更新的问题)。谢谢!
      • 找到根本原因了吗? @coreyward。我在这里有类似的问题stackoverflow.com/questions/38778689/…
      【解决方案4】:

      查询是从您的应用程序中的用户输入生成的吗?如果是这样,如果您没有控制用户输入,那么可能是有人试图破解您的应用程序的 sql 注入。

      http://en.wikipedia.org/wiki/SQL_injection

      我对 Rails 不是很熟悉,所以我不知道它是否自动创建了您作为开发人员不知道的查询,但我不这么认为。

      【讨论】:

      • 这不太可能。这是对已知/预期 URL 的 GET 请求。
      • 明白了。我正在学习 php 并阅读了很多关于这类事情的内容,所以我想我会把它扔在那里以防万一:) 看起来你已经在其他讨论中得到了它!
      猜你喜欢
      • 1970-01-01
      • 2017-01-19
      • 2011-11-29
      • 2018-11-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      相关资源
      最近更新 更多