试试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。