Postgres failover

Documentation
Login

Hi!

Attached patch which implements client library failover and loadbalancing as was described in the proposal <20150818041850.GA5092@wagner.pp.ru>.

This patch implements following fuctionality:

  1. It is allowed to specify several hosts in the connect string, either in URL-style (separated by comma) or in param=value form (several host parameters).

  2. Each host parameter can be accompanied with port specifier separated by colon. Port, specified such way takes precedence of port parameter or default port for this particular host only.

  3. There is hostorder parameter with two possible valies 'sequential' and 'random' (default sequential). 'parallel' hostorder described in the proposal is not yet implemented in this version of patch.

  4. In the URL-style connect string parameter loadBalanceHosts=true is considered equal to 'hostorder=random' for compatibility with jdbc.

  5. Added new parameter readonly=boolean. If this parameter is false (the default) upon successful connection check is performed that backend is not in the recovery state. If so, connection is not considered usable and next host is tried.

  6. Added new parameter falover_timeout. If no usable host is found and this parameter is specified, hosts are retried cyclically until this timeout expires. It gives some time for claster management software to promote one of standbys to master if master fails. By default there is no retries.

Some implementation notes:

  1. Field pghost in the PGconn structure now stores comma separated list of hosts, which is parsed in the connectDBStart. So, expected results of some tests in src/interfaces/libpq/test are changed.

  2. Url with colon but no port number after the host no more considered valid.

  3. With hostorder=random we have to seed libc random number gernerator. Some care was taken to not to lose entropy if generator was initialized by app before connection, and to ensure different random values if several connections are made from same application in one second (even in single thread). RNG is seeded by xor of current time, random value from this rng before seeding (if it was seeded earlier, it keeps entropy) and address of the connection structure. May be it worth effort adding thread id or pid, but there is no portable way to doing so, so it would need testing on all supported platform.