mysql - Rails 如何构建 MySQL 语句?

标签 mysql ruby-on-rails ruby heroku

我有以下代码在 Controller 内的 heroku 上运行,间歇性地 失败。它应该对我有用,这是显而易见的,但我一定遗漏了一些东西。

@artist = Artist.find(params[:artist_id])

参数散列如下所示:

{"utf8"=>"������",
 "authenticity_token"=>"XXXXXXXXXXXXXXX",
 "password"=>"[FILTERED]",
 "commit"=>"Download",
 "action"=>"show",
 "controller"=>"albums",
 "artist_id"=>"62",
 "id"=>"157"}

我得到的错误是这样的:

ActiveRecord::StatementInvalid: Mysql::Error: : SELECT `artists`.* FROM `artists` WHERE `artists`.`id` = ? LIMIT 1

注意到声明中的 WHEREartists.id= ? 部分了吗?它正在尝试查找 QUESTION MARK 的 ID。这意味着 Rails 没有传入 params[:artist_id],这显然在 params 散列中。我完全不知所措。

我在尝试以类似方式选择记录的不同页面上遇到相同的错误。

我的环境:Heroku 上的 Cedar Stack(这发生在 Heroku 上),Ruby 1.9.3,Rails 3.2.8,文件托管在 Amazon S3 上(尽管我怀疑这是否重要),使用mysql gem(不是 mysql2,它根本不起作用),ClearDB MySQL 数据库。

这是 full trace .

我们将非常感谢任何帮助。

最佳答案

试试sql?

如果只是这一条语句,并且它导致了生产问题,您可以暂时忽略查询生成器吗?换句话说,短期内,只需自己编写 SQL。这将为您赢得一些时间。

# All on one line:
Artist.find_by_sql
  "SELECT `artists`.* FROM `artists` 
   WHERE `artists`.`id` = #{params[:artist_id].to_i} LIMIT 1"

ARel/MySQL 解释一下?

Rails 可以帮助解释 MySQL 试图做什么:

Artist.find(params[:artist_id]).explain

http://weblog.rubyonrails.org/2011/12/6/what-s-new-in-edge-rails-explain/

也许您会发现成功查询与失败查询之间的某种差异,例如explain 如何使用索引或优化。

mysql2 gem?

您可以尝试从 mysql gem 更改为 mysql2 gem 吗?当您切换到 mysql2 gem 时会遇到什么故障?

波动性?

也许有其他东西在动态改变参数散列,所以当你打印它时你会看到它,但它在查询运行时已经改变了?

尝试在收到参数后立即分配变量:

artist_id = params[:artist_id]
... whatever code here...
@artist = Artist.find(artist_id)

不是参数散列?

您写道“意思是 Rails 没有传入参数 [:artist_id],这显然在参数散列中。”我认为这不是问题所在——我希望您看到这个是因为 Rails 使用“?”作为准备好的语句的占位符。

要找出答案,请运行@Mori 建议的命令并进行比较;他们应该是一样的。

Article.find(42).to_sql
Article.find(params[:artist_id]).to_sql

准备好的陈述?

当实际执行查询时,可能是准备语句缓存问题。

这是失败的代码——并且有一个很大的警告。

begin
  stmt.execute(*binds.map { |col, val| type_cast(val, col) })
rescue Mysql::Error => e
  # Older versions of MySQL leave the prepared statement in a bad
  # place when an error occurs. To support older mysql versions, we
  # need to close the statement and delete the statement from the
  # cache.
  stmt.close
  @statements.delete sql
  raise e
end

尝试配置您的数据库以关闭准备好的语句,看看是否有所不同。

在你的 ./config/database.yml 文件中:

production:
   adapter: mysql
   prepared_statements: false
   ...

准备好的语句有错误吗?

Rails 忽略此设置可能存在问题。如果您想了解更多信息,请参阅 Jeremey Cole 和 Aaron 的讨论和错误修复:https://github.com/rails/rails/pull/7042

Heroku 可能会忽略该设置。您可以通过修补 prepared_statements 设置来尝试覆盖 Heroku:https://github.com/rails/rails/issues/5297

删除查询缓存?

尝试删除 ActiveRecord QueryCache 以查看是否有所不同:

config.middleware.delete ActiveRecord::QueryCache

http://edgeguides.rubyonrails.org/configuring.html#configuring-middle

试试 postgres?

如果您可以尝试 Postgres,那也可以解决问题。这对您来说可能不是一个长期的解决方案,但它会将问题隔离到 MySQL。

关于mysql - Rails 如何构建 MySQL 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12517073/

相关文章:

php - 我应该什么时候删除用户的登录 cookie?

php - 尽管我有,但没有选择数据库

php - 如何在 PHP 中从 sql 表填充下拉菜单

链接到另一列的更新属性上的 Mysql 时间戳

ruby-on-rails - 无法安装 Ruby 1.9.3

ruby-on-rails - 滑轨轮胎:使用自定义逻辑导入

ruby-on-rails - 未找到 id 为 primary 的连接池

ruby-on-rails - 在 Ruby 中,您能否在调用子方法时从主方法决定返回或继续?

ruby-on-rails - 多次验证Rails 3(僵尸铁路; 2 :3)

ruby-on-rails - rails : has_many through association - did I get this right?