1

我有以下代码在间歇性失败的控制器内的 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艺术家.ID= ?部分了吗?它正在尝试查找 QUESTION MARK 的 ID。这意味着 Rails 没有传入params[:artist_id]显然在 params 哈希中的。我完全失去了。

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

我的环境:Heroku 上的 Cedar Stack(这只发生在 Heroku 上)、Ruby 1.9.3、Rails 3.2.8、托管在 Amazon S3 上的文件(尽管我怀疑这很重要),使用mysqlgem(不是mysql2,这不起作用完全),ClearDB MySQL 数据库。

这是完整的跟踪

任何帮助将不胜感激。

4

2 回答 2

6

试试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宝石?

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

挥发性?

也许还有其他东西在动态更改参数哈希,所以您在打印它时会看到它,但是在查询运行时它已经改变了?

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

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

不是参数哈希?

你写了“意思是 Rails 没有传入 params[:artist_id] 这显然在 params 哈希中。” 我认为这不是问题——我希望您会看到这一点,因为 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。

于 2012-09-25T05:55:16.843 回答
1

MySQL 语句显然是错误的,但您提到的 Ruby 代码不会产生它。这里出了点问题,要么使用不同的 Ruby 代码(可能来自 before_filter),要么传递不同的参数(如 params[:artist_id] = "?")。看起来您使用嵌套资源,例如Artist has_many :albums. 也许@artist 变量在前面的操作中没有正确初始化,所以 params[:artist_id] 没有正确的值?

于 2012-09-25T09:00:11.127 回答