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:
		
							
								
								
									
										120
									
								
								bin/pg_repack.c
									
									
									
									
									
								
							
							
						
						
									
										120
									
								
								bin/pg_repack.c
									
									
									
									
									
								
							| @ -143,6 +143,24 @@ const char *PROGRAM_VERSION = "unknown"; | |||||||
| /* Will be used as a unique prefix for advisory locks. */ | /* Will be used as a unique prefix for advisory locks. */ | ||||||
| #define REPACK_LOCK_PREFIX_STR "16185446" | #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 |  * per-table information | ||||||
|  */ |  */ | ||||||
| @ -167,27 +185,11 @@ typedef struct repack_table | |||||||
| 	const char	   *sql_delete;		/* SQL used in flush */ | 	const char	   *sql_delete;		/* SQL used in flush */ | ||||||
| 	const char	   *sql_update;		/* SQL used in flush */ | 	const char	   *sql_update;		/* SQL used in flush */ | ||||||
| 	const char	   *sql_pop;		/* 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; | } 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 bool is_superuser(void); | ||||||
| static void check_tablespace(void); | static void check_tablespace(void); | ||||||
| static bool preliminary_checks(char *errbuf, size_t errsize); | 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 *create_table_2; | ||||||
| 		const char *tablespace; | 		const char *tablespace; | ||||||
| 		const char *ckey; | 		const char *ckey; | ||||||
|  | 		PGresult   *indexres = NULL; | ||||||
|  | 		const char *indexparams[2]; | ||||||
|  | 		char		buffer[12]; | ||||||
|  | 		int         j; | ||||||
| 		int			c = 0; | 		int			c = 0; | ||||||
|  |  | ||||||
| 		table.target_name = getstr(res, i, c++); | 		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; | 			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); | 		repack_one_table(&table, orderby); | ||||||
| 	} | 	} | ||||||
| 	ret = true; | 	ret = true; | ||||||
| @ -777,40 +818,17 @@ apply_log(PGconn *conn, const repack_table *table, int count) | |||||||
| static bool | static bool | ||||||
| rebuild_indexes(const repack_table *table) | rebuild_indexes(const repack_table *table) | ||||||
| { | { | ||||||
| 	PGresult	   *res; | 	PGresult	   *res = NULL; | ||||||
| 	const char	   *params[2]; |  | ||||||
| 	int			    num_indexes; | 	int			    num_indexes; | ||||||
| 	int				i; | 	int				i; | ||||||
| 	int				num_active_workers; | 	int				num_active_workers; | ||||||
| 	int				num_workers; | 	int				num_workers; | ||||||
| 	repack_index   *index_jobs; | 	repack_index   *index_jobs; | ||||||
| 	char			buffer[12]; |  | ||||||
| 	bool            have_error = false; | 	bool            have_error = false; | ||||||
|  |  | ||||||
| 	elog(DEBUG2, "---- create indexes ----"); | 	elog(DEBUG2, "---- create indexes ----"); | ||||||
|  |  | ||||||
| 	params[0] = utoa(table->target_oid, buffer); | 	num_indexes = table->n_indexes; | ||||||
| 	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); |  | ||||||
|  |  | ||||||
| 	/* We might have more actual worker connections than we need, | 	/* We might have more actual worker connections than we need, | ||||||
| 	 * if the number of workers exceeds the number of indexes to be | 	 * 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, | 	elog(DEBUG2, "Have %d indexes and num_workers=%d", num_indexes, | ||||||
| 		 num_workers); | 		 num_workers); | ||||||
|  |  | ||||||
| 	index_jobs = pgut_malloc(sizeof(repack_index) * num_indexes); | 	index_jobs = table->indexes; | ||||||
|  |  | ||||||
| 	for (i = 0; i < num_indexes; i++) | 	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, "set up index_jobs [%d]", i); | ||||||
| 		elog(DEBUG2, "target_oid   : %u", index_jobs[i].target_oid); | 		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. | 		 * available. That's OK, we'll get to them later. | ||||||
| 		 */ | 		 */ | ||||||
| 	} | 	} | ||||||
| 	CLEARPGRES(res); |  | ||||||
|  |  | ||||||
| 	if (num_workers > 1) | 	if (num_workers > 1) | ||||||
| 	{ | 	{ | ||||||
| @ -1016,7 +1027,7 @@ repack_one_table(const repack_table *table, const char *orderby) | |||||||
| 	const char	   *params[2]; | 	const char	   *params[2]; | ||||||
| 	int				num; | 	int				num; | ||||||
| 	int				num_waiting = 0; | 	int				num_waiting = 0; | ||||||
|  | 	int             i; | ||||||
| 	char		   *vxid = NULL; | 	char		   *vxid = NULL; | ||||||
| 	char			buffer[12]; | 	char			buffer[12]; | ||||||
| 	StringInfoData	sql; | 	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_delete     : %s", table->sql_delete); | ||||||
| 	elog(DEBUG2, "sql_update     : %s", table->sql_update); | 	elog(DEBUG2, "sql_update     : %s", table->sql_update); | ||||||
| 	elog(DEBUG2, "sql_pop        : %s", table->sql_pop); | 	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) | 	if (dryrun) | ||||||
| 		return; | 		return; | ||||||
|  | |||||||
| @ -117,16 +117,16 @@ SELECT * FROM tbl_with_dropped_toast; | |||||||
| \! pg_repack --dbname=contrib_regression --table=tbl_cluster | \! pg_repack --dbname=contrib_regression --table=tbl_cluster | ||||||
| INFO: repacking table "tbl_cluster" | INFO: repacking table "tbl_cluster" | ||||||
| \! pg_repack --dbname=contrib_regression --table=tbl_badindex | \! 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) | 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 | \! pg_repack --dbname=contrib_regression | ||||||
| INFO: repacking table "tbl_cluster" | INFO: repacking table "tbl_cluster" | ||||||
| INFO: repacking table "tbl_only_pkey" | INFO: repacking table "tbl_only_pkey" | ||||||
| INFO: repacking table "tbl_gistkey" | INFO: repacking table "tbl_gistkey" | ||||||
| INFO: repacking table "tbl_with_dropped_column" | INFO: repacking table "tbl_with_dropped_column" | ||||||
| INFO: repacking table "tbl_with_dropped_toast" | 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) | 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" | INFO: repacking table "tbl_idxopts" | ||||||
| -- | -- | ||||||
| -- after | -- after | ||||||
|  | |||||||
		Reference in New Issue
	
	Block a user