Gather index info at the same time as table info, rather than later.

This helps avoid possible problems with later strong table locks.
This commit is contained in:
Andrew Dunstan 2014-12-30 10:48:35 -05:00
parent 6d3c085b22
commit 9f77a2fd03
2 changed files with 70 additions and 54 deletions

View File

@ -143,6 +143,24 @@ const char *PROGRAM_VERSION = "unknown";
/* Will be used as a unique prefix for advisory locks. */
#define REPACK_LOCK_PREFIX_STR "16185446"
typedef enum
{
UNPROCESSED,
INPROGRESS,
FINISHED
} index_status_t;
/*
* per-index information
*/
typedef struct repack_index
{
Oid target_oid; /* target: OID */
const char *create_index; /* CREATE INDEX */
index_status_t status; /* Track parallel build statuses. */
int worker_idx; /* which worker conn is handling */
} repack_index;
/*
* per-table information
*/
@ -167,27 +185,11 @@ typedef struct repack_table
const char *sql_delete; /* SQL used in flush */
const char *sql_update; /* SQL used in flush */
const char *sql_pop; /* SQL used in flush */
int n_indexes; /* number of indexes */
repack_index *indexes; /* info on each index */
} repack_table;
typedef enum
{
UNPROCESSED,
INPROGRESS,
FINISHED
} index_status_t;
/*
* per-index information
*/
typedef struct repack_index
{
Oid target_oid; /* target: OID */
const char *create_index; /* CREATE INDEX */
index_status_t status; /* Track parallel build statuses. */
int worker_idx; /* which worker conn is handling */
} repack_index;
static bool is_superuser(void);
static void check_tablespace(void);
static bool preliminary_checks(char *errbuf, size_t errsize);
@ -667,6 +669,10 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
const char *create_table_2;
const char *tablespace;
const char *ckey;
PGresult *indexres = NULL;
const char *indexparams[2];
char buffer[12];
int j;
int c = 0;
table.target_name = getstr(res, i, c++);
@ -735,6 +741,41 @@ repack_one_database(const char *orderby, char *errbuf, size_t errsize)
table.create_table = sql.data;
}
indexparams[0] = utoa(table.target_oid, buffer);
indexparams[1] = moveidx ? tablespace : NULL;
/* First, just display a warning message for any invalid indexes
* which may be on the table (mostly to match the behavior of 1.1.8).
*/
indexres = execute(
"SELECT pg_get_indexdef(indexrelid)"
" FROM pg_index WHERE indrelid = $1 AND NOT indisvalid",
1, indexparams);
for (j = 0; j < PQntuples(indexres); j++)
{
const char *indexdef;
indexdef = getstr(indexres, j, 0);
elog(WARNING, "skipping invalid index: %s", indexdef);
}
indexres = execute(
"SELECT indexrelid,"
" repack.repack_indexdef(indexrelid, indrelid, $2, FALSE) "
" FROM pg_index WHERE indrelid = $1 AND indisvalid",
2, indexparams);
table.n_indexes = PQntuples(indexres);
table.indexes = pgut_malloc(table.n_indexes * sizeof(repack_index));
for (j = 0; j < table.n_indexes; j++)
{
table.indexes[j].target_oid = getoid(indexres, j, 0);
table.indexes[j].create_index = getstr(indexres, j, 1);
table.indexes[j].status = UNPROCESSED;
table.indexes[j].worker_idx = -1; /* Unassigned */
}
repack_one_table(&table, orderby);
}
ret = true;
@ -777,40 +818,17 @@ apply_log(PGconn *conn, const repack_table *table, int count)
static bool
rebuild_indexes(const repack_table *table)
{
PGresult *res;
const char *params[2];
PGresult *res = NULL;
int num_indexes;
int i;
int num_active_workers;
int num_workers;
repack_index *index_jobs;
char buffer[12];
bool have_error = false;
elog(DEBUG2, "---- create indexes ----");
params[0] = utoa(table->target_oid, buffer);
params[1] = moveidx ? tablespace : NULL;
/* First, just display a warning message for any invalid indexes
* which may be on the table (mostly to match the behavior of 1.1.8).
*/
res = execute("SELECT pg_get_indexdef(indexrelid)"
" FROM pg_index WHERE indrelid = $1 AND NOT indisvalid",
1, params);
for (i = 0; i < PQntuples(res); i++)
{
const char *indexdef;
indexdef = getstr(res, i, 0);
elog(WARNING, "skipping invalid index: %s", indexdef);
}
res = execute("SELECT indexrelid,"
" repack.repack_indexdef(indexrelid, indrelid, $2, FALSE) "
" FROM pg_index WHERE indrelid = $1 AND indisvalid",
2, params);
num_indexes = PQntuples(res);
num_indexes = table->n_indexes;
/* We might have more actual worker connections than we need,
* if the number of workers exceeds the number of indexes to be
@ -822,16 +840,10 @@ rebuild_indexes(const repack_table *table)
elog(DEBUG2, "Have %d indexes and num_workers=%d", num_indexes,
num_workers);
index_jobs = pgut_malloc(sizeof(repack_index) * num_indexes);
index_jobs = table->indexes;
for (i = 0; i < num_indexes; i++)
{
int c = 0;
index_jobs[i].target_oid = getoid(res, i, c++);
index_jobs[i].create_index = getstr(res, i, c++);
index_jobs[i].status = UNPROCESSED;
index_jobs[i].worker_idx = -1; /* Unassigned */
elog(DEBUG2, "set up index_jobs [%d]", i);
elog(DEBUG2, "target_oid : %u", index_jobs[i].target_oid);
@ -868,7 +880,6 @@ rebuild_indexes(const repack_table *table)
* available. That's OK, we'll get to them later.
*/
}
CLEARPGRES(res);
if (num_workers > 1)
{
@ -1016,7 +1027,7 @@ repack_one_table(const repack_table *table, const char *orderby)
const char *params[2];
int num;
int num_waiting = 0;
int i;
char *vxid = NULL;
char buffer[12];
StringInfoData sql;
@ -1054,6 +1065,11 @@ repack_one_table(const repack_table *table, const char *orderby)
elog(DEBUG2, "sql_delete : %s", table->sql_delete);
elog(DEBUG2, "sql_update : %s", table->sql_update);
elog(DEBUG2, "sql_pop : %s", table->sql_pop);
for (i = 0; i < table->n_indexes; i++)
{
elog(DEBUG2, "index[%d].target_oid : %u", i, table->indexes[i].target_oid);
elog(DEBUG2, "index[%d].create_index : %s", i, table->indexes[i].create_index);
}
if (dryrun)
return;

View File

@ -117,16 +117,16 @@ SELECT * FROM tbl_with_dropped_toast;
\! pg_repack --dbname=contrib_regression --table=tbl_cluster
INFO: repacking table "tbl_cluster"
\! pg_repack --dbname=contrib_regression --table=tbl_badindex
INFO: repacking table "tbl_badindex"
WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n)
INFO: repacking table "tbl_badindex"
\! pg_repack --dbname=contrib_regression
INFO: repacking table "tbl_cluster"
INFO: repacking table "tbl_only_pkey"
INFO: repacking table "tbl_gistkey"
INFO: repacking table "tbl_with_dropped_column"
INFO: repacking table "tbl_with_dropped_toast"
INFO: repacking table "tbl_badindex"
WARNING: skipping invalid index: CREATE UNIQUE INDEX idx_badindex_n ON tbl_badindex USING btree (n)
INFO: repacking table "tbl_badindex"
INFO: repacking table "tbl_idxopts"
--
-- after