sql >> Databasteknik >  >> RDS >> Mysql

Hur bygger Rails ett MySQL-uttalande?

prova sql?

Om det bara är det här påståendet och det orsakar produktionsproblem, kan du utelämna frågegeneratorn just nu? Med andra ord, på mycket kort sikt, skriv bara SQL själv. Detta kommer att ge dig lite tid.

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

ARel/MySQL förklara?

Rails kan hjälpa till att förklara vad MySQL försöker göra:

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

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

Kanske kan du upptäcka någon form av skillnad mellan de frågor som lyckas och misslyckas, till exempel hur explain använder index eller optimeringar.

mysql2 pärla?

Kan du prova att byta från mysql pärla till mysql2 pärla? Vilket misslyckande får du när du byter till mysql2 pärla?

volatilitet?

Kanske är det något annat som ändrar params hash i farten, så du ser det när du skriver ut det, men det har ändrats när frågan körs?

Försök att tilldela variabeln så snart du får parametrarna:

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

inte params hash?

Du skrev "Det betyder att Rails inte passerar i params[:artist_id] som uppenbarligen finns i params-hash." Jag tror inte att det är problemet - jag förväntar mig att du ser detta eftersom Rails använder "?" som platshållare för ett förberett uttalande.

För att ta reda på det, kör kommandona som föreslagits av @Mori och jämför dem; de borde vara samma.

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

förberedda uttalanden?

Kan vara ett problem med förberedd satscache när frågan faktiskt körs.

Här är koden som misslyckas – och det finns en stor fet varning.

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

Försök att konfigurera din databas för att stänga av förberedda uttalanden, för att se om det gör någon skillnad.

I din ./config/database.yml fil:

production:
   adapter: mysql
   prepared_statements: false
   ...

buggar med förberedda uttalanden?

Det kan finnas ett problem med att Rails ignorerar den här inställningen. Om du vill veta mycket mer om det, se denna diskussion och buggfix av Jeremey Cole och Aaron:https://github.com/rails/rails/pull/7042

Heroku kan ignorera inställningen. Här är ett sätt att försöka åsidosätta Heroku genom att korrigera inställningarna för preparerade_statements:https://github.com /rails/rails/issues/5297

ta bort frågecachen?

Försök att ta bort ActiveRecord QueryCache för att se om det gör någon skillnad:

config.middleware.delete ActiveRecord::QueryCache

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

prova postgres?

Om du kan prova Postgres kan det också reda ut det. Det kanske inte är en långsiktig lösning för dig, men det skulle isolera problemet till MySQL.



  1. Oracle 12c Ubuntu 17.04 Installationsfel

  2. Välj ett inlägg som inte har en viss tagg

  3. Använder pyspark för att ansluta till PostgreSQL

  4. Har databaser förutom Postgres funktioner som är jämförbara med utländska dataomslag?