wypróbować sql?
Jeśli to tylko ta jedna instrukcja i powoduje problemy produkcyjne, czy możesz na razie pominąć generator zapytań? Innymi słowy, na bardzo krótki okres, po prostu napisz sam SQL. To da ci trochę czasu.
# All on one line:
Artist.find_by_sql
"SELECT `artists`.* FROM `artists`
WHERE `artists`.`id` = #{params[:artist_id].to_i} LIMIT 1"
Wyjaśnienie dotyczące ARel/MySQL?
Railsy mogą pomóc wyjaśnić, co MySQL próbuje zrobić:
Artist.find(params[:artist_id]).explain
http://weblog.rubyonrails.org/2011/12/6/what-s-new-in-edge-rails-explain/
Być może możesz odkryć jakąś różnicę między zapytaniami, które kończą się powodzeniem a niepowodzeniem, na przykład jak explain
używa indeksów lub optymalizacji.
klejnot mysql2?
Czy możesz spróbować zmienić z klejnotu mysql na klejnot mysql2? Jaką porażkę otrzymujesz po przejściu na klejnot mysql2?
zmienność?
Być może jest coś innego zmieniającego hash params w locie, więc widzisz to po wydrukowaniu, ale zmienia się to do czasu uruchomienia zapytania?
Spróbuj przypisać zmienną, gdy tylko otrzymasz parametry:
artist_id = params[:artist_id]
... whatever code here...
@artist = Artist.find(artist_id)
nie hash params?
Napisałeś "Oznacza to, że Railsy nie przekazują params[:artist_id], który oczywiście znajduje się w hashu params." Nie sądzę, że to jest problem — spodziewam się, że widzisz to, ponieważ Railsy używają znaku „?” jako symbol zastępczy dla przygotowanej instrukcji.
Aby się dowiedzieć, uruchom polecenia sugerowane przez @Mori i porównaj je; powinny być takie same.
Article.find(42).to_sql
Article.find(params[:artist_id]).to_sql
przygotowane zestawienia?
Może to być problem z pamięcią podręczną przygotowanych instrukcji, gdy zapytanie jest faktycznie wykonywane.
Oto kod, który zawodzi – i jest duże ostrzeżenie.
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
Spróbuj skonfigurować bazę danych tak, aby wyłączyć przygotowywane instrukcje, aby zobaczyć, czy to robi różnicę.
W swoim ./config/database.yml
plik:
production:
adapter: mysql
prepared_statements: false
...
błędy z przygotowanymi wyciągami?
Może wystąpić problem z ignorowaniem tego ustawienia przez Railsy. Jeśli chcesz dowiedzieć się więcej na ten temat, zobacz tę dyskusję i naprawę błędów autorstwa Jeremeya Cole'a i Aarona:https://github.com/rails/rails/pull/7042
Heroku może zignorować to ustawienie. Oto sposób, w jaki możesz spróbować ominąć Heroku, łatając konfigurację ready_statements:https://github.com /rails/rails/issues/5297
usunąć pamięć podręczną zapytań?
Spróbuj usunąć ActiveRecord QueryCache, aby zobaczyć, czy to robi różnicę:
config.middleware.delete ActiveRecord::QueryCache
http://edgeguides.rubyonrails.org/configuring.html#configuring-middle
wypróbować postgres?
Jeśli możesz wypróbować Postgres, to również może to wyjaśnić. To może nie być długoterminowe rozwiązanie dla Ciebie, ale odizolowałoby problem od MySQL.