Skip to content

Commit 09ef2f8

Browse files
committed
reindexdb: Fix the index-level REINDEX with multiple jobs
47f99a4 introduced a parallel index-level REINDEX. The code was written assuming that running run_reindex_command() with 'async == true' can schedule a number of queries for a connection. That's not true, and the second query sent using run_reindex_command() will wait for the completion of the previous one. This commit fixes that by putting REINDEX commands for the same table into a single query. Also, this commit removes the 'async' argument from run_reindex_command(), as only its call always passes 'async == true'. Reported-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Discussion: https://postgr.es/m/202503071820.j25zn3lo4hvn%40alvherre.pgsql Reviewed-by: Álvaro Herrera <alvherre@alvh.no-ip.org> Backpatch-through: 17
1 parent c826cd1 commit 09ef2f8

File tree

1 file changed

+73
-62
lines changed

1 file changed

+73
-62
lines changed

src/bin/scripts/reindexdb.c

Lines changed: 73 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -50,10 +50,13 @@ static void reindex_all_databases(ConnParams *cparams,
5050
bool syscatalog, SimpleStringList *schemas,
5151
SimpleStringList *tables,
5252
SimpleStringList *indexes);
53-
static void run_reindex_command(PGconn *conn, ReindexType type,
53+
static void gen_reindex_command(PGconn *conn, ReindexType type,
5454
const char *name, bool echo, bool verbose,
55-
bool concurrently, bool async,
56-
const char *tablespace);
55+
bool concurrently, const char *tablespace,
56+
PQExpBufferData *sql);
57+
static void run_reindex_command(PGconn *conn, ReindexType type,
58+
const char *name, bool echo,
59+
PQExpBufferData *sq);
5760

5861
static void help(const char *progname);
5962

@@ -285,7 +288,6 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
285288
ParallelSlotArray *sa;
286289
bool failed = false;
287290
int items_count = 0;
288-
char *prev_index_table_name = NULL;
289291
ParallelSlot *free_slot = NULL;
290292

291293
conn = connectDatabase(cparams, progname, echo, false, true);
@@ -421,44 +423,54 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
421423
cell = process_list->head;
422424
do
423425
{
426+
PQExpBufferData sql;
424427
const char *objname = cell->val;
425-
bool need_new_slot = true;
426428

427429
if (CancelRequested)
428430
{
429431
failed = true;
430432
goto finish;
431433
}
432434

433-
/*
434-
* For parallel index-level REINDEX, the indices of the same table are
435-
* ordered together and they are to be processed by the same job. So,
436-
* we don't switch the job as soon as the index belongs to the same
437-
* table as the previous one.
438-
*/
439-
if (parallel && process_type == REINDEX_INDEX)
435+
free_slot = ParallelSlotsGetIdle(sa, NULL);
436+
if (!free_slot)
440437
{
441-
if (prev_index_table_name != NULL &&
442-
strcmp(prev_index_table_name, indices_tables_cell->val) == 0)
443-
need_new_slot = false;
444-
prev_index_table_name = indices_tables_cell->val;
445-
indices_tables_cell = indices_tables_cell->next;
438+
failed = true;
439+
goto finish;
446440
}
447441

448-
if (need_new_slot)
442+
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
443+
initPQExpBuffer(&sql);
444+
if (parallel && process_type == REINDEX_INDEX)
449445
{
450-
free_slot = ParallelSlotsGetIdle(sa, NULL);
451-
if (!free_slot)
446+
/*
447+
* For parallel index-level REINDEX, the indices of the same table
448+
* are ordered together and they are to be processed by the same
449+
* job. So, we put all the relevant REINDEX commands into the
450+
* same SQL query to be processed by this job at once.
451+
*/
452+
gen_reindex_command(free_slot->connection, process_type, objname,
453+
echo, verbose, concurrently, tablespace, &sql);
454+
while (indices_tables_cell->next &&
455+
strcmp(indices_tables_cell->val, indices_tables_cell->next->val) == 0)
452456
{
453-
failed = true;
454-
goto finish;
457+
indices_tables_cell = indices_tables_cell->next;
458+
cell = cell->next;
459+
objname = cell->val;
460+
appendPQExpBufferChar(&sql, '\n');
461+
gen_reindex_command(free_slot->connection, process_type, objname,
462+
echo, verbose, concurrently, tablespace, &sql);
455463
}
456-
457-
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
464+
indices_tables_cell = indices_tables_cell->next;
465+
}
466+
else
467+
{
468+
gen_reindex_command(free_slot->connection, process_type, objname,
469+
echo, verbose, concurrently, tablespace, &sql);
458470
}
459-
460471
run_reindex_command(free_slot->connection, process_type, objname,
461-
echo, verbose, concurrently, true, tablespace);
472+
echo, &sql);
473+
termPQExpBuffer(&sql);
462474

463475
cell = cell->next;
464476
} while (cell != NULL);
@@ -486,57 +498,57 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
486498
exit(1);
487499
}
488500

501+
/*
502+
* Append a SQL command required to reindex a given database object to the
503+
* '*sql' string.
504+
*/
489505
static void
490-
run_reindex_command(PGconn *conn, ReindexType type, const char *name,
491-
bool echo, bool verbose, bool concurrently, bool async,
492-
const char *tablespace)
506+
gen_reindex_command(PGconn *conn, ReindexType type, const char *name,
507+
bool echo, bool verbose, bool concurrently,
508+
const char *tablespace, PQExpBufferData *sql)
493509
{
494510
const char *paren = "(";
495511
const char *comma = ", ";
496512
const char *sep = paren;
497-
PQExpBufferData sql;
498-
bool status;
499513

500514
Assert(name);
501515

502516
/* build the REINDEX query */
503-
initPQExpBuffer(&sql);
504-
505-
appendPQExpBufferStr(&sql, "REINDEX ");
517+
appendPQExpBufferStr(sql, "REINDEX ");
506518

507519
if (verbose)
508520
{
509-
appendPQExpBuffer(&sql, "%sVERBOSE", sep);
521+
appendPQExpBuffer(sql, "%sVERBOSE", sep);
510522
sep = comma;
511523
}
512524

513525
if (tablespace)
514526
{
515-
appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep,
527+
appendPQExpBuffer(sql, "%sTABLESPACE %s", sep,
516528
fmtIdEnc(tablespace, PQclientEncoding(conn)));
517529
sep = comma;
518530
}
519531

520532
if (sep != paren)
521-
appendPQExpBufferStr(&sql, ") ");
533+
appendPQExpBufferStr(sql, ") ");
522534

523535
/* object type */
524536
switch (type)
525537
{
526538
case REINDEX_DATABASE:
527-
appendPQExpBufferStr(&sql, "DATABASE ");
539+
appendPQExpBufferStr(sql, "DATABASE ");
528540
break;
529541
case REINDEX_INDEX:
530-
appendPQExpBufferStr(&sql, "INDEX ");
542+
appendPQExpBufferStr(sql, "INDEX ");
531543
break;
532544
case REINDEX_SCHEMA:
533-
appendPQExpBufferStr(&sql, "SCHEMA ");
545+
appendPQExpBufferStr(sql, "SCHEMA ");
534546
break;
535547
case REINDEX_SYSTEM:
536-
appendPQExpBufferStr(&sql, "SYSTEM ");
548+
appendPQExpBufferStr(sql, "SYSTEM ");
537549
break;
538550
case REINDEX_TABLE:
539-
appendPQExpBufferStr(&sql, "TABLE ");
551+
appendPQExpBufferStr(sql, "TABLE ");
540552
break;
541553
}
542554

@@ -546,37 +558,43 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
546558
* object type.
547559
*/
548560
if (concurrently)
549-
appendPQExpBufferStr(&sql, "CONCURRENTLY ");
561+
appendPQExpBufferStr(sql, "CONCURRENTLY ");
550562

551563
/* object name */
552564
switch (type)
553565
{
554566
case REINDEX_DATABASE:
555567
case REINDEX_SYSTEM:
556-
appendPQExpBufferStr(&sql,
568+
appendPQExpBufferStr(sql,
557569
fmtIdEnc(name, PQclientEncoding(conn)));
558570
break;
559571
case REINDEX_INDEX:
560572
case REINDEX_TABLE:
561-
appendQualifiedRelation(&sql, name, conn, echo);
573+
appendQualifiedRelation(sql, name, conn, echo);
562574
break;
563575
case REINDEX_SCHEMA:
564-
appendPQExpBufferStr(&sql, name);
576+
appendPQExpBufferStr(sql, name);
565577
break;
566578
}
567579

568580
/* finish the query */
569-
appendPQExpBufferChar(&sql, ';');
581+
appendPQExpBufferChar(sql, ';');
582+
}
570583

571-
if (async)
572-
{
573-
if (echo)
574-
printf("%s\n", sql.data);
584+
/*
585+
* Run one or more reindex commands accumulated in the '*sql' string against
586+
* a given database connection.
587+
*/
588+
static void
589+
run_reindex_command(PGconn *conn, ReindexType type, const char *name,
590+
bool echo, PQExpBufferData *sql)
591+
{
592+
bool status;
575593

576-
status = PQsendQuery(conn, sql.data) == 1;
577-
}
578-
else
579-
status = executeMaintenanceCommand(conn, sql.data, echo);
594+
if (echo)
595+
printf("%s\n", sql->data);
596+
597+
status = PQsendQuery(conn, sql->data) == 1;
580598

581599
if (!status)
582600
{
@@ -603,14 +621,7 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
603621
name, PQdb(conn), PQerrorMessage(conn));
604622
break;
605623
}
606-
if (!async)
607-
{
608-
PQfinish(conn);
609-
exit(1);
610-
}
611624
}
612-
613-
termPQExpBuffer(&sql);
614625
}
615626

616627
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy