Mysql
 sql >> Database >  >> RDS >> Mysql

In che modo Rails crea un'istruzione MySQL?

provare sql?

Se è solo questa affermazione e sta causando problemi di produzione, puoi omettere il generatore di query solo per ora? In altre parole, per brevissimo termine, scrivi tu stesso l'SQL. Questo ti farà guadagnare un po' di tempo.

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

ARel/MySQL spiega?

Rails può aiutare a spiegare cosa sta cercando di fare MySQL:

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

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

Forse puoi scoprire una sorta di differenza tra le query che hanno esito positivo e quelle non riuscite, ad esempio come il explain utilizza indici o ottimizzazioni.

gemma mysql2?

Puoi provare a cambiare dalla gemma mysql alla gemma mysql2? Che errore ricevi quando passi alla gemma mysql2?

volatilità?

Forse c'è qualcos'altro che cambia al volo l'hash dei parametri, quindi lo vedi quando lo stampi, ma è cambiato quando viene eseguita la query?

Prova ad assegnare la variabile non appena ricevi i parametri:

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

non l'hash dei parametri?

Hai scritto "Significa che Rails non sta passando nei parametri [:artist_id] che è ovviamente nell'hash dei parametri". Non credo che sia questo il problema:mi aspetto che tu lo veda perché Rails sta usando il "?" come segnaposto per una dichiarazione preparata.

Per scoprirlo, esegui i comandi suggeriti da @Mori e confrontali; dovrebbero essere gli stessi.

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

dichiarazioni preparate?

Potrebbe essere un problema di cache delle istruzioni preparate, quando la query viene effettivamente eseguita.

Ecco il codice che non riesce e c'è un grosso avviso.

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

Prova a configurare il tuo database per disattivare le istruzioni preparate, per vedere se questo fa la differenza.

Nel tuo ./config/database.yml file:

production:
   adapter: mysql
   prepared_statements: false
   ...

bug con istruzioni preparate?

Potrebbe esserci un problema con Rails che ignora questa impostazione. Se vuoi saperne di più, consulta questa discussione e la correzione dei bug di Jeremey Cole e Aaron:https://github.com/rails/rails/pull/7042

Heroku potrebbe ignorare l'impostazione. Ecco un modo in cui puoi provare a sovrascrivere Heroku correggendo l'impostazione prepare_statements:https://github.com /rails/rails/issues/5297

rimuovere la cache delle query?

Prova a rimuovere ActiveRecord QueryCache per vedere se questo fa la differenza:

config.middleware.delete ActiveRecord::QueryCache

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

provare Postgres?

Se puoi provare Postgres, anche questo potrebbe chiarire. Potrebbe non essere una soluzione a lungo termine per te, ma isolerebbe il problema su MySQL.