Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

Como o Rails constrói uma instrução MySQL?

experimentar sql?


Se for apenas esta declaração e estiver causando problemas de produção, você pode omitir o gerador de consulta por enquanto? Em outras palavras, para um prazo muito curto, basta escrever o SQL você mesmo. Isso vai lhe dar um pouco de 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 explica?


Rails pode ajudar a explicar o que o MySQL está tentando fazer:
Artist.find(params[:artist_id]).explain

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

Talvez você possa descobrir algum tipo de diferença entre as consultas que estão sendo bem-sucedidas e as que falham, por exemplo, como o explain usa índices ou otimizações.

gem do mysql2?


Você pode tentar mudar da gem mysql para a gem mysql2? Que falha você obtém quando muda para a gem mysql2?

volatilidade?


Talvez haja algo mais alterando o hash de params em tempo real, então você o vê quando o imprime, mas é alterado no momento em que a consulta é executada?

Tente atribuir a variável assim que receber os parâmetros:
artist_id = params[:artist_id]
... whatever code here...
@artist = Artist.find(artist_id)

não é o hash de parâmetros?


Você escreveu "O que significa que Rails não está passando no params[:artist_id] que obviamente está no hash de params." Eu não acho que esse seja o problema-- espero que você esteja vendo isso porque o Rails está usando o "?" como um espaço reservado para uma declaração preparada.

Para descobrir, execute os comandos sugeridos por @Mori e compare-os; Eles deveriam ser os mesmos.
Article.find(42).to_sql
Article.find(params[:artist_id]).to_sql

declarações preparadas?


Pode ser um problema de cache de instrução preparada, quando a consulta é realmente executada.

Aqui está o código que está falhando - e há um grande aviso.
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

Tente configurar seu banco de dados para desativar as instruções preparadas, para ver se isso faz diferença.

Em seu ./config/database.yml Arquivo:
production:
   adapter: mysql
   prepared_statements: false
   ...

bugs com declarações preparadas?


Pode haver um problema com o Rails ignorando esta configuração. Se você quiser saber muito mais sobre isso, veja esta discussão e correção de bug por Jeremey Cole e Aaron:https://github.com/rails/rails/pull/7042

Heroku pode ignorar a configuração. Aqui está uma maneira de tentar substituir o Heroku corrigindo a configuração de prepare_statements:https://github.com /rails/rails/issues/5297

remover o cache de consulta?


Tente remover o ActiveRecord QueryCache para ver se isso faz alguma diferença:
config.middleware.delete ActiveRecord::QueryCache

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

experimentar postgres?


Se você puder tentar o Postgres, isso também pode esclarecer. Isso pode não ser uma solução de longo prazo para você, mas isolaria o problema do MySQL.