Usando SQLAlchemy para consultar um banco de dados PostgreSQL atrás de PgBouncer, usando pooling em nível de transação.
Qual é o melhor padrão a ser usado para esse tipo de configuração? Devo ter um mecanismo por processo, usando um ConnectionPool
, ou devo criar um mecanismo por solicitação e usar NullPool
para cada um deles? Existe um padrão completamente diferente que eu deveria usar?
Muito obrigado! Deixe-me saber se mais informações são necessárias e atualizarei o mais rápido possível.
com o PGBouncer, você provavelmente gostaria de ficar com o NullPool. Nesse caso, você poderá compartilhar um único mecanismo entre os subprocessos, pois nenhuma conexão de soquete será transportada para o limite do subprocesso. Mas você não pode compartilhar nada referente a um objeto Connection, como uma Session com uma transação ativa, além desse limite. Você definitivamente não gostaria de fazer "mecanismo por solicitação", porém, um mecanismo é um objeto caro que acumula muitas informações sobre um determinado URL de banco de dados na primeira vez que o vê.
Defina o nome do aplicativo
Se você espera executar muitos processos, precisa saber de onde eles estão se conectando. O PGBouncer tornará isso invisível para
pg_stat_activity
. Resolva isso definindo cuidadosamente oapplication_name
com as informações necessárias:Preferir Sessões
Use sessões, pois as solicitações de um objeto Engine podem gerar e manter várias conexões. Conectar-se ao Postgres não é muito caro, com o PGBouncer é ainda menos. Eu sempre usaria
NullPool
para que as únicas conexões que você verá no Postgres sejam as conexões que estão realmente sendo usadas.Eliminar transações ociosas
Se sua intenção é usar o PGBouncer para escalar, é imperativo que você evite deixar as transações travadas em aberto.
autocommit
Para fazer isso , você precisa ativar . Isso não é simples com o SQLAlchemy... existem três lugares onde algo chamado "autocommit" pode ser definido:psycopg2 autocommit
Presume-se que não seja seguro porque o SQLAlchemy precisa saber o que está acontecendo por baixo.
Sessão autocommit
Isso requer uma entrega cuidadosa e explícita:
A chamada de função e o tratamento de exceções são extremamente difíceis porque
begin()
nãocommit()
podem ser aninhados:Neste modo, psycopg2
autocommit
parece serFalse
(o padrão)Confirmação automática do mecanismo
Definir o modo de isolamento do mecanismo para
"AUTOCOMMIT"
ao criar o mecanismo estabelece um novo comportamento padrão que pode não exigir alterações no código existente.Neste modo, o psycopg2
autocommit
parece serTrue
O grande problema aqui é que a única forma de garantir que um bloco de código seja encapsulado em uma transação é emitir as instruções manualmente: