Edge Rails: Pool de Conexões no Rails

9 de setembro de 2008  |  Rails 2.2  | 

Algo que muita gente reclama sobre o Rails é que ele é lento. Sabemos que isto não é totalmente verdade, mas também sabemos que muita coisa pode ser feita para melhorar a performance dele.

Uma destas coisas acabou de se feita. Foi incluído ao Rails um Pool de Conexões com o banco de dados.

Toda vez que uma requisição ao banco de dados é feita, perde-se algum tempo criando uma nova conexão e só depois é que a pesquisa ou gravação é realizada. Olhando superficialmente pode parecer algo muito rápido e simples, mas abrir uma conexão com o banco de dados não é tão simples assim. É necessário estabelecer uma conexão física com o servidor do banco, autenticar a conexão e realizar mais uma série de validações. Tudo isto consome recursos e tempo. Isto explica muito bem o porque de o banco de dados se tornar o vilão de alguns grandes projetos criados em Rails.

A solução para este tipo de problema é reaproveitar conexões já criadas para realizar mais tarefas dentro do banco de dados antes de fecha-las. Ou em termos mais técnicos, precisamos de um Pool de Conexões.

O processo é o seguinte: Uma conexão com o banco de dados é aberta e utilizada para realizar uma pesquisa. Depois disso, ao invés de fecha-la, ela é armazena no pool de conexões. Quando uma outra requisição é feita, ao invés de abrir uma nova conexão, o sistema reaproveita uma que já foi aberta, diminuindo o tempo e os recursos necessários para realizar a tarefa. Várias conexões podem ser armazenadas no pool ao mesmo tempo.

No Rails será criado um novo pool para cada execução do método establish_connection. Em outras palavras, cada banco de dados cadastrado no arquivo database.yml terá seu próprio pool de conexões.

O pool começa vazio e vai crescendo até o limite de 5 conexões (padrão), mas você pode aumentar este limite acrescentando a opção ‘pool‘ na configuração do banco de dados.

development:
  adapter: mysql
  host: localhost
  username: myuser
  password: mypass
  database: somedatabase
  pool: 10
  wait_timeout: 15

Se nenhuma das conexões estiver disponível, uma thread irá esperar durante 5 segundos (padrão) e tentar novamente. Este tempo também pode ser configurado adicionando a chave ‘wait_timeout‘ na configuração do banco de dados.

Se você desejar usar o pool de conexões fora do ActionPack, existe o método ActiveRecord::Base.connection_pool que permite que você manualmente faça o checkout/checkin das conexões. Não esqueça de fazer o checkin quando terminar de usar a conexão.

connection = ActiveRecord::Base.connection_pool.checkout

# faz alguma coisa no banco de dados

ActiveRecord::Base.connection_pool.checkin(connection)

Você também pode usar o método ActiveRecord::Base.connection_pool.with_connection que já faz o checkout/checkin automaticamente para você, tornando-se uma opção mais segura.

ActiveRecord::Base.connection_pool.with_connection do |connection|
  # faz alguma coisa no banco de dados
end


10 Comentários


  1. olá carlos

    essa funcionalidade pode ser usando no rails 2.1.1 ou apenas nas futuras versões?

    grande abraço

  2. Será que agora com pool de conexões, Drivers Assíncronos e rails thread-safe, o Rails vai escalar?

    ;-)

    obs: seria interessante fazer um benchmark juntando tudo isso… futuras idéias…

  3. Bom lembrar que isso só faz sentido com o Rails em modo thread-safe.

    Um abraço!

  4. Carlos tudo bem?

    Uma dúvida, talvez você consiga me ajudar. Me utilizo de tabelas temporárias em um banco de dados DB2 na minha aplicação.

    Com o esquema de conexões do rails ele se aproveita de uma conexão que está inativa o que para mim não é bom, já que se tiver duas aplicações fazendo o mesmo processo ao mesmo tempo, as conexões podem se misturar e assim a mesma tabela temporária pode ser utilizado nos dois casos.

    Tem como eu resolver esse problema de alguma forma?

  5. Alair,

    Você chegou a testar? Este recurso na teoria só funcionará se você estiver usando JRuby.

  6. Testei com o pool de conexões, porém acontece essa situação, uma sessão do rails acaba acessando a tabela temporaria da outra, o que não pode acontecer.

    Acredito que vou ter que tirar mesmo essa questão da temporary table do banco de dados e tentar resolver isso no próprio rails.

    Muito obrigado Carlos.

  7. Alair,

    Você não deveria usar transações?

  8. Não entendi. O que voce chama de transação?

Trackbacks

  1. Green Threads, Native Threads, GIL, Ruby e Rails… | papodenerd.net

Deixe um comentário