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

Hvordan bygger Rails en MySQL-erklæring?

prøve sql?

Hvis det kun er dette ene udsagn, og det forårsager produktionsproblemer, kan du så udelade forespørgselsgeneratoren lige nu? Med andre ord, på meget kort sigt skal du bare skrive SQL'en selv. Dette vil give dig lidt 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 forklare?

Rails kan hjælpe med at forklare, hvad MySQL forsøger at gøre:

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

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

Måske kan du opdage en eller anden form for forskel mellem de forespørgsler, der lykkes i forhold til mislykkede, såsom hvordan explain bruger indekser eller optimeringer.

mysql2 perle?

Kan du prøve at skifte fra mysql-perlen til mysql2-perlen? Hvilken fejl får du, når du skifter til mysql2-perlen?

volatilitet?

Måske er der noget andet, der ændrer params-hashen i farten, så du kan se det, når du udskriver det, men det er ændret, når forespørgslen kører?

Prøv at tildele variablen, så snart du modtager parametrene:

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

ikke params hash?

Du skrev "Det betyder, at Rails ikke passerer i params[:artist_id] som åbenbart er i params hash." Jeg tror ikke, det er problemet - jeg forventer, at du ser dette, fordi Rails bruger "?" som pladsholder for en udarbejdet erklæring.

For at finde ud af det, kør kommandoerne foreslået af @Mori og sammenlign dem; de skal være de samme.

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

forberedte erklæringer?

Kunne være et forberedt sætningscacheproblem, når forespørgslen rent faktisk udføres.

Her er koden, der fejler - og der er en stor fed advarsel.

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

Prøv at konfigurere din database til at slå forberedte sætninger fra for at se, om det gør en forskel.

I din ./config/database.yml fil:

production:
   adapter: mysql
   prepared_statements: false
   ...

fejl med forberedte udsagn?

Der kan være et problem med, at Rails ignorerer denne indstilling. Hvis du vil vide meget mere om det, så se denne diskussion og fejlrettelse af Jeremey Cole og Aaron:https://github.com/rails/rails/pull/7042

Heroku ignorerer muligvis indstillingen. Her er en måde, hvorpå du kan prøve at tilsidesætte Heroku ved at rette opsætningen af ​​preparerte_statements:https://github.com /rails/rails/issues/5297

fjerne forespørgselscachen?

Prøv at fjerne ActiveRecord QueryCache for at se, om det gør en forskel:

config.middleware.delete ActiveRecord::QueryCache

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

prøve postgres?

Hvis du kan prøve Postgres, kan det også rydde op. Det er måske ikke en langsigtet løsning for dig, men det ville isolere problemet til MySQL.



  1. Sådan opsætter du Oracle EBS Auditing

  2. Hvordan man implementerer multidimensionelle sekvenser

  3. Hvordan arbejder man med javax.persistence.sql-load-script-source?

  4. Den angivne nøgle var for lang; max nøglelængde er 767 bytes Mysql-fejl i Entity Framework 6