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.
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;
--------
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)
{
"\tRESUME [<db>]\n"
"\tDISABLE <db>\n"
"\tENABLE <db>\n"
+ "\tRECONNECT [<db>]\n"
"\tKILL <db>\n"
"\tSUSPEND\n"
"\tSHUTDOWN", "");
{"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},
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'"
test_enable_disable
test_database_restart
test_database_change
+test_reconnect
"
if [ $# -gt 0 ]; then