Fabrízio de Royes Mello

Blog sobre Tecnologia da Informação

Case PgBouncer 1.3 Com PostgreSQL 8.2

Pessoal,

Estou finalizando a implantação do PgBouncer 1.3 com PostgreSQL 8.2 e obtive excelentes resultados só pelo fato de colocar o Pool de Conexões na frente do “postmaster”.

Até aqui não temos nada de muito surpreendente a não ser pelo fato de que, segundo a documentação do próprio PgBouncer fala que podemos ter 100% de transparência com o PostgreSQL 8.3 pelo fato do comando ”DISCARD” estar presente apartir dessa release.

Como na versão que estamos utilizando, a 8.2, não existe essa implementação então o jeito foi implementar uma PL que “emule” o comportamento do ”DISCARD”.

Através da lista de discussão da Comunidade Brasileira de PostgreSQL (pgbr-geral), com a ajuda do colega Euler, implementei uma PL para suprir essa falta conforme segue:

create or replace function fc_discard_all() returns void as
$$
declare
rComando record;
iVersao integer;
begin

select cast(setting as integer)
into iVersao
from pg_settings
where name ~ 'server_version_num';

if not found then
raise exception 'A versão do PostgreSQL deve ser >= 8.2';
end if;

if iVersao >= 80300 then
execute 'discard all';
return;
end if;

set session authorization default;

reset all;

for rComando in
select name
from pg_prepared_statements
loop
execute 'deallocate '||rComando.name;
end loop;

for rComando in
select name
from pg_cursors
where name not like '%unnamed%'
loop
execute 'close '||rComando.name;
end loop;

unlisten *;

perform pg_advisory_unlock_all();

for rComando in
select distinct
table_schema,
table_name
from information_schema.tables
where table_type = 'LOCAL TEMPORARY'
loop
execute 'drop table if exists '||quote_ident(rComando.table_schema)||'.'||quote_ident(rComando.table_name)||' cascade';
end loop;

return;
end;
$$
language plpgsql;

No meu arquivo de configuração do pool (pgbouncer.ini) fiz o seguinte:

server_reset_query = SELECT fc_discard_all()


Os únicos efeitos colaterais dessa solução são:
  1. Se a base de dados que for acessada não tiver a PL acima criada vai gerar um log de erro, mas não impacta em problemas na conexão
  2. Não foi possível implementar uma emulação para o DISCARD PLANS pois, segundo o colega Euler, esse comando veio em conjunto com a funcionalidade de invalidação de planos em funções procedurais, logo não pode ser emulada em versões menores que 8.3
Tive de implementar esse recurso pois preciso descartar tabelas temporárias e outros recursos que são utilizados pela minha aplicação.

O modo do pool que estou utilizando é o “session” pois preciso da sessão do inicio ao fim com o mesmo estado.

Se alguém tiver alguma dica e/ou critica estou a disposição.


Cordialmente,

Fabrízio de Royes Mello
fabriziomello [at] gmail.com