
= PgBouncer FAQ =

== How to load-balance queries between several servers? ==

Use a TCP connection load-balancer.  Either http://www.linuxvirtualserver.org/[LVS]
or http://haproxy.1wt.eu/[HAProxy] seem to be good choices.  On PgBouncer
side it may be good idea to make `server_lifetime` smaller and also
turn `server_round_robin` on - by default idle connections are
reused by LIFO algorithm which may work not so well when
load-balancing is needed.


== How to use SSL connections with PgBouncer? ==

Use http://www.stunnel.org/[Stunnel].  Since version 4.27 it
supports PostgreSQL protocol for both client and server side.
It is activated by setting `protocol=pgsql`.

For older 4.2x versions the support code is available as patch:
http://pgbouncer.projects.postgresql.org/patches/stunnel-postgres.diff[stunnel-postgres.diff]

Alternative is to use Stunnel on both sides of connection,
then the protocol support is not needed.


== How to use prepared statements with PgBouncer? ==

These tricks are mostly needed for JDBC which just loves them.

=== Session pooling with PostgreSQL 8.3 and newer ===

This is easy - just set `server_reset_query = DISCARD ALL;`
or at least to `DEALLOCATE ALL;`

=== Session pooling with PostgreSQL 8.2 and older ===

This is problematic as older versions of PostgreSQL do not allow
easy way to drop prepared statements.  Luckily there is system
view that shows prepared plans in current session.  So as a workaround
following function can be created:

    CREATE OR REPLACE FUNCTION deallocate_all()
    RETURNS void AS $$
    DECLARE
	sql text;
    BEGIN
	FOR sql IN
	    SELECT 'deallocate ' || quote_ident(name)
	      FROM pg_catalog.pg_prepared_statements
	LOOP
	    EXECUTE sql;
	END LOOP;
    END;
    $$ LANGUAGE plpgsql;

Then the `server_reset_query` can be set to call it:

    server_reset_query = RESET ALL; SET SESSION AUTHORIZATION DEFAULT; SELECT deallocate_all();


=== Transaction pooling ===

To make prepared statements work in this mode would need PgBouncer
to keep track of them internally, which it does not do.  So only way to
keep using PgBouncer in this mode is to disable prepared statements
completely.

The proper way to do it for JDBC is adding `prepareThreshold=0`
parameter to connect string.  But current JDBC code ignores
the setting for BEGIN/COMMIT/ROLLBACK statements and still
tries to cache their plans.  This can be fixed with following patch:

http://treehou.se/~omar/postgresql-jdbc-8.4-701-pgbouncer_txn.patch[]

described here:

http://pgfoundry.org/pipermail/pgbouncer-general/2010-February/000507.html[]


== How to upgrade PgBouncer without dropping connections? ==

This is as easy as launching new PgBouncer process with `-R` switch
and same config:

    $ pgbouncer -R -d config.ini

The `-R` (reboot) switch makes new process connect to console
of the old process (dbname=pgbouncer), issue following commands:

  SUSPEND;
  SHOW FDS;
  SHUTDOWN;

After that if new one notices old one gone it resumes work with
old connections.  The magic happens during `SHOW FDS` command which
transports actual file descriptors to new process.

If the takeover does not work for whatever reason, the new process
can be simply killed, old one notices this and resumes work.


