vacuumdb: enable parallel mode

This mode allows vacuumdb to open several server connections to vacuum
or analyze several tables simultaneously.

Author: Dilip Kumar.  Some reworking by Álvaro Herrera
Reviewed by: Jeff Janes, Amit Kapila, Magnus Hagander, Andres Freund
This commit is contained in:
Alvaro Herrera 2015-01-23 15:02:45 -03:00
parent 5cefbf5a6c
commit a179232047
5 changed files with 721 additions and 191 deletions

View File

@ -203,6 +203,30 @@ PostgreSQL documentation
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>-j <replaceable class="parameter">njobs</replaceable></option></term>
<term><option>--jobs=<replaceable class="parameter">njobs</replaceable></option></term>
<listitem>
<para>
Execute the vacuum or analyze commands in parallel by running
<replaceable class="parameter">njobs</replaceable>
commands simultaneously. This option reduces the time of the
processing but it also increases the load on the database server.
</para>
<para>
<application>vacuumdb</application> will open
<replaceable class="parameter">njobs</replaceable> connections to the
database, so make sure your <xref linkend="guc-max-connections">
setting is high enough to accommodate all connections.
</para>
<para>
Note that using this mode together with the <option>-f</option>
(<literal>FULL</literal>) option might cause deadlock failures if
certain system catalogs are processed in parallel.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>--analyze-in-stages</option></term> <term><option>--analyze-in-stages</option></term>
<listitem> <listitem>

View File

@ -1160,7 +1160,7 @@ select_loop(int maxFd, fd_set *workerset)
i = select(maxFd + 1, workerset, NULL, NULL, NULL); i = select(maxFd + 1, workerset, NULL, NULL, NULL);
/* /*
* If we Ctrl-C the master process , it's likely that we interrupt * If we Ctrl-C the master process, it's likely that we interrupt
* select() here. The signal handler will set wantAbort == true and * select() here. The signal handler will set wantAbort == true and
* the shutdown journey starts from here. Note that we'll come back * the shutdown journey starts from here. Note that we'll come back
* here later when we tell all workers to terminate and read their * here later when we tell all workers to terminate and read their

View File

@ -19,10 +19,9 @@
#include "common.h" #include "common.h"
static void SetCancelConn(PGconn *conn);
static void ResetCancelConn(void);
static PGcancel *volatile cancelConn = NULL; static PGcancel *volatile cancelConn = NULL;
bool CancelRequested = false;
#ifdef WIN32 #ifdef WIN32
static CRITICAL_SECTION cancelConnLock; static CRITICAL_SECTION cancelConnLock;
@ -291,7 +290,7 @@ yesno_prompt(const char *question)
* *
* Set cancelConn to point to the current database connection. * Set cancelConn to point to the current database connection.
*/ */
static void void
SetCancelConn(PGconn *conn) SetCancelConn(PGconn *conn)
{ {
PGcancel *oldCancelConn; PGcancel *oldCancelConn;
@ -321,7 +320,7 @@ SetCancelConn(PGconn *conn)
* *
* Free the current cancel connection, if any, and set to NULL. * Free the current cancel connection, if any, and set to NULL.
*/ */
static void void
ResetCancelConn(void) ResetCancelConn(void)
{ {
PGcancel *oldCancelConn; PGcancel *oldCancelConn;
@ -345,9 +344,8 @@ ResetCancelConn(void)
#ifndef WIN32 #ifndef WIN32
/* /*
* Handle interrupt signals by canceling the current command, * Handle interrupt signals by canceling the current command, if a cancelConn
* if it's being executed through executeMaintenanceCommand(), * is set.
* and thus has a cancelConn set.
*/ */
static void static void
handle_sigint(SIGNAL_ARGS) handle_sigint(SIGNAL_ARGS)
@ -359,10 +357,15 @@ handle_sigint(SIGNAL_ARGS)
if (cancelConn != NULL) if (cancelConn != NULL)
{ {
if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
{
CancelRequested = true;
fprintf(stderr, _("Cancel request sent\n")); fprintf(stderr, _("Cancel request sent\n"));
}
else else
fprintf(stderr, _("Could not send cancel request: %s"), errbuf); fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
} }
else
CancelRequested = true;
errno = save_errno; /* just in case the write changed it */ errno = save_errno; /* just in case the write changed it */
} }
@ -392,10 +395,16 @@ consoleHandler(DWORD dwCtrlType)
if (cancelConn != NULL) if (cancelConn != NULL)
{ {
if (PQcancel(cancelConn, errbuf, sizeof(errbuf))) if (PQcancel(cancelConn, errbuf, sizeof(errbuf)))
{
fprintf(stderr, _("Cancel request sent\n")); fprintf(stderr, _("Cancel request sent\n"));
CancelRequested = true;
}
else else
fprintf(stderr, _("Could not send cancel request: %s"), errbuf); fprintf(stderr, _("Could not send cancel request: %s"), errbuf);
} }
else
CancelRequested = true;
LeaveCriticalSection(&cancelConnLock); LeaveCriticalSection(&cancelConnLock);
return TRUE; return TRUE;

View File

@ -21,6 +21,8 @@ enum trivalue
TRI_YES TRI_YES
}; };
extern bool CancelRequested;
typedef void (*help_handler) (const char *progname); typedef void (*help_handler) (const char *progname);
extern void handle_help_version_opts(int argc, char *argv[], extern void handle_help_version_opts(int argc, char *argv[],
@ -49,4 +51,8 @@ extern bool yesno_prompt(const char *question);
extern void setup_cancel_handler(void); extern void setup_cancel_handler(void);
extern void SetCancelConn(PGconn *conn);
extern void ResetCancelConn(void);
#endif /* COMMON_H */ #endif /* COMMON_H */

File diff suppressed because it is too large Load Diff