我有以下代码在 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
注意到声明中的 WHERE
artists.
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/