From: Peter Eisentraut Date: Wed, 25 Jul 2018 09:18:01 +0000 (+0200) Subject: RECONNECT command X-Git-Tag: pgbouncer_1_9_0~6 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=e24d1fa303f877238e2b6f5141cde3506e9f7b49;p=pgbouncer RECONNECT command --- diff --git a/doc/usage.rst b/doc/usage.rst index aeac92d..3e62d8c 100644 --- a/doc/usage.rst +++ b/doc/usage.rst @@ -276,7 +276,7 @@ wait_us close_needed 1 if the connection will be closed as soon as possible, because a configuration file reload or DNS update changed the - connection information. + connection information or **RECONNECT** was issued. ptr Address of internal object for this connection. @@ -596,6 +596,33 @@ ENABLE db; Allow new client connections after a previous **DISABLE** command. +RECONNECT [db]; +--------------- + +Close each open server connection for the given database, or all +databases, after it is released (according to the pooling mode), even +if its lifetime is not up yet. New server connections can be made +immediately and will connect as necessary according to the pool size +settings. + +This command is useful when the server connection setup has changed, +for example to perform a gradual switchover to a new server. It is +*not* necessary to run this command when the connection string in +pgbouncer.ini has been changed and reloaded (see **RELOAD**) or when +DNS resolution has changed, because then the equivalent of this +command will be run automatically. This command is only necessary if +something downstream of PgBouncer routes the connections. + +After this command is run, there could be an extended period where +some server connections go to an old destination and some server +connections go to a new destination. This is likely only sensible +when switching read-only traffic between read-only replicas, or when +switching between nodes of a multimaster replication setup. If all +connections need to be switched at the same time, **PAUSE** is +recommended instead. To close server connections without waiting (for +example, in emergency failover rather than gradual switchover +scenarios), also consider **KILL**. + KILL db; -------- diff --git a/src/admin.c b/src/admin.c index e4dd684..a86fb45 100644 --- a/src/admin.c +++ b/src/admin.c @@ -1075,6 +1075,38 @@ static bool admin_cmd_pause(PgSocket *admin, const char *arg) return true; } +/* Command: RECONNECT */ +static bool admin_cmd_reconnect(PgSocket *admin, const char *arg) +{ + if (!admin->admin_user) + return admin_error(admin, "admin access needed"); + + if (!arg[0]) { + struct List *item; + PgPool *pool; + + log_info("RECONNECT command issued"); + statlist_for_each(item, &pool_list) { + pool = container_of(item, PgPool, head); + if (pool->db->admin) + continue; + tag_database_dirty(pool->db); + } + } else { + PgDatabase *db; + + log_info("RECONNECT '%s' command issued", arg); + db = find_or_register_database(admin, arg); + if (db == NULL) + return admin_error(admin, "no such database: %s", arg); + if (db == admin->pool->db) + return admin_error(admin, "cannot reconnect admin db: %s", arg); + tag_database_dirty(db); + } + + return admin_ready(admin, "RECONNECT"); +} + /* Command: DISABLE */ static bool admin_cmd_disable(PgSocket *admin, const char *arg) { @@ -1210,6 +1242,7 @@ static bool admin_show_help(PgSocket *admin, const char *arg) "\tRESUME []\n" "\tDISABLE \n" "\tENABLE \n" + "\tRECONNECT []\n" "\tKILL \n" "\tSUSPEND\n" "\tSHUTDOWN", ""); @@ -1285,6 +1318,7 @@ static struct cmd_lookup cmd_list [] = { {"enable", admin_cmd_enable}, {"kill", admin_cmd_kill}, {"pause", admin_cmd_pause}, + {"reconnect", admin_cmd_reconnect}, {"reload", admin_cmd_reload}, {"resume", admin_cmd_resume}, {"select", admin_cmd_show}, diff --git a/test/test.sh b/test/test.sh index 2ebb530..5fc6758 100755 --- a/test/test.sh +++ b/test/test.sh @@ -458,6 +458,16 @@ test_database_change() { test "$db1" = "p1" -a "$db2" = "p0" } +# test reconnect +test_reconnect() { + bp1=`psql -X -tAq -c "select pg_backend_pid()" p1` + admin "reconnect p1" + sleep 1 + bp2=`psql -X -tAq -c "select pg_backend_pid()" p1` + echo "bp1=$bp1 bp2=$bp2" + test "$bp1" != "$bp2" +} + # test auth_user test_auth_user() { admin "set auth_type='md5'" @@ -497,6 +507,7 @@ test_suspend_resume test_enable_disable test_database_restart test_database_change +test_reconnect " if [ $# -gt 0 ]; then