Skip to content

Commit 682c5be

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 83e5763 commit 682c5be

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
@@ -49,10 +49,13 @@ static void reindex_all_databases(ConnParams *cparams,
4949
bool syscatalog, SimpleStringList *schemas,
5050
SimpleStringList *tables,
5151
SimpleStringList *indexes);
52-
static void run_reindex_command(PGconn *conn, ReindexType type,
52+
static void gen_reindex_command(PGconn *conn, ReindexType type,
5353
const char *name, bool echo, bool verbose,
54-
bool concurrently, bool async,
55-
const char *tablespace);
54+
bool concurrently, const char *tablespace,
55+
PQExpBufferData *sql);
56+
static void run_reindex_command(PGconn *conn, ReindexType type,
57+
const char *name, bool echo,
58+
PQExpBufferData *sq);
5659

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

@@ -284,7 +287,6 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
284287
ParallelSlotArray *sa;
285288
bool failed = false;
286289
int items_count = 0;
287-
char *prev_index_table_name = NULL;
288290
ParallelSlot *free_slot = NULL;
289291

290292
conn = connectDatabase(cparams, progname, echo, false, true);
@@ -430,44 +432,54 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
430432
cell = process_list->head;
431433
do
432434
{
435+
PQExpBufferData sql;
433436
const char *objname = cell->val;
434-
bool need_new_slot = true;
435437

436438
if (CancelRequested)
437439
{
438440
failed = true;
439441
goto finish;
440442
}
441443

442-
/*
443-
* For parallel index-level REINDEX, the indices of the same table are
444-
* ordered together and they are to be processed by the same job. So,
445-
* we don't switch the job as soon as the index belongs to the same
446-
* table as the previous one.
447-
*/
448-
if (parallel && process_type == REINDEX_INDEX)
444+
free_slot = ParallelSlotsGetIdle(sa, NULL);
445+
if (!free_slot)
449446
{
450-
if (prev_index_table_name != NULL &&
451-
strcmp(prev_index_table_name, indices_tables_cell->val) == 0)
452-
need_new_slot = false;
453-
prev_index_table_name = indices_tables_cell->val;
454-
indices_tables_cell = indices_tables_cell->next;
447+
failed = true;
448+
goto finish;
455449
}
456450

457-
if (need_new_slot)
451+
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
452+
initPQExpBuffer(&sql);
453+
if (parallel && process_type == REINDEX_INDEX)
458454
{
459-
free_slot = ParallelSlotsGetIdle(sa, NULL);
460-
if (!free_slot)
455+
/*
456+
* For parallel index-level REINDEX, the indices of the same table
457+
* are ordered together and they are to be processed by the same
458+
* job. So, we put all the relevant REINDEX commands into the
459+
* same SQL query to be processed by this job at once.
460+
*/
461+
gen_reindex_command(free_slot->connection, process_type, objname,
462+
echo, verbose, concurrently, tablespace, &sql);
463+
while (indices_tables_cell->next &&
464+
strcmp(indices_tables_cell->val, indices_tables_cell->next->val) == 0)
461465
{
462-
failed = true;
463-
goto finish;
466+
indices_tables_cell = indices_tables_cell->next;
467+
cell = cell->next;
468+
objname = cell->val;
469+
appendPQExpBufferChar(&sql, '\n');
470+
gen_reindex_command(free_slot->connection, process_type, objname,
471+
echo, verbose, concurrently, tablespace, &sql);
464472
}
465-
466-
ParallelSlotSetHandler(free_slot, TableCommandResultHandler, NULL);
473+
indices_tables_cell = indices_tables_cell->next;
474+
}
475+
else
476+
{
477+
gen_reindex_command(free_slot->connection, process_type, objname,
478+
echo, verbose, concurrently, tablespace, &sql);
467479
}
468-
469480
run_reindex_command(free_slot->connection, process_type, objname,
470-
echo, verbose, concurrently, true, tablespace);
481+
echo, &sql);
482+
termPQExpBuffer(&sql);
471483

472484
cell = cell->next;
473485
} while (cell != NULL);
@@ -495,57 +507,57 @@ reindex_one_database(ConnParams *cparams, ReindexType type,
495507
exit(1);
496508
}
497509

510+
/*
511+
* Append a SQL command required to reindex a given database object to the
512+
* '*sql' string.
513+
*/
498514
static void
499-
run_reindex_command(PGconn *conn, ReindexType type, const char *name,
500-
bool echo, bool verbose, bool concurrently, bool async,
501-
const char *tablespace)
515+
gen_reindex_command(PGconn *conn, ReindexType type, const char *name,
516+
bool echo, bool verbose, bool concurrently,
517+
const char *tablespace, PQExpBufferData *sql)
502518
{
503519
const char *paren = "(";
504520
const char *comma = ", ";
505521
const char *sep = paren;
506-
PQExpBufferData sql;
507-
bool status;
508522

509523
Assert(name);
510524

511525
/* build the REINDEX query */
512-
initPQExpBuffer(&sql);
513-
514-
appendPQExpBufferStr(&sql, "REINDEX ");
526+
appendPQExpBufferStr(sql, "REINDEX ");
515527

516528
if (verbose)
517529
{
518-
appendPQExpBuffer(&sql, "%sVERBOSE", sep);
530+
appendPQExpBuffer(sql, "%sVERBOSE", sep);
519531
sep = comma;
520532
}
521533

522534
if (tablespace)
523535
{
524-
appendPQExpBuffer(&sql, "%sTABLESPACE %s", sep,
536+
appendPQExpBuffer(sql, "%sTABLESPACE %s", sep,
525537
fmtIdEnc(tablespace, PQclientEncoding(conn)));
526538
sep = comma;
527539
}
528540

529541
if (sep != paren)
530-
appendPQExpBufferStr(&sql, ") ");
542+
appendPQExpBufferStr(sql, ") ");
531543

532544
/* object type */
533545
switch (type)
534546
{
535547
case REINDEX_DATABASE:
536-
appendPQExpBufferStr(&sql, "DATABASE ");
548+
appendPQExpBufferStr(sql, "DATABASE ");
537549
break;
538550
case REINDEX_INDEX:
539-
appendPQExpBufferStr(&sql, "INDEX ");
551+
appendPQExpBufferStr(sql, "INDEX ");
540552
break;
541553
case REINDEX_SCHEMA:
542-
appendPQExpBufferStr(&sql, "SCHEMA ");
554+
appendPQExpBufferStr(sql, "SCHEMA ");
543555
break;
544556
case REINDEX_SYSTEM:
545-
appendPQExpBufferStr(&sql, "SYSTEM ");
557+
appendPQExpBufferStr(sql, "SYSTEM ");
546558
break;
547559
case REINDEX_TABLE:
548-
appendPQExpBufferStr(&sql, "TABLE ");
560+
appendPQExpBufferStr(sql, "TABLE ");
549561
break;
550562
}
551563

@@ -555,37 +567,43 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
555567
* object type.
556568
*/
557569
if (concurrently)
558-
appendPQExpBufferStr(&sql, "CONCURRENTLY ");
570+
appendPQExpBufferStr(sql, "CONCURRENTLY ");
559571

560572
/* object name */
561573
switch (type)
562574
{
563575
case REINDEX_DATABASE:
564576
case REINDEX_SYSTEM:
565-
appendPQExpBufferStr(&sql,
577+
appendPQExpBufferStr(sql,
566578
fmtIdEnc(name, PQclientEncoding(conn)));
567579
break;
568580
case REINDEX_INDEX:
569581
case REINDEX_TABLE:
570-
appendQualifiedRelation(&sql, name, conn, echo);
582+
appendQualifiedRelation(sql, name, conn, echo);
571583
break;
572584
case REINDEX_SCHEMA:
573-
appendPQExpBufferStr(&sql, name);
585+
appendPQExpBufferStr(sql, name);
574586
break;
575587
}
576588

577589
/* finish the query */
578-
appendPQExpBufferChar(&sql, ';');
590+
appendPQExpBufferChar(sql, ';');
591+
}
579592

580-
if (async)
581-
{
582-
if (echo)
583-
printf("%s\n", sql.data);
593+
/*
594+
* Run one or more reindex commands accumulated in the '*sql' string against
595+
* a given database connection.
596+
*/
597+
static void
598+
run_reindex_command(PGconn *conn, ReindexType type, const char *name,
599+
bool echo, PQExpBufferData *sql)
600+
{
601+
bool status;
584602

585-
status = PQsendQuery(conn, sql.data) == 1;
586-
}
587-
else
588-
status = executeMaintenanceCommand(conn, sql.data, echo);
603+
if (echo)
604+
printf("%s\n", sql->data);
605+
606+
status = PQsendQuery(conn, sql->data) == 1;
589607

590608
if (!status)
591609
{
@@ -612,14 +630,7 @@ run_reindex_command(PGconn *conn, ReindexType type, const char *name,
612630
name, PQdb(conn), PQerrorMessage(conn));
613631
break;
614632
}
615-
if (!async)
616-
{
617-
PQfinish(conn);
618-
exit(1);
619-
}
620633
}
621-
622-
termPQExpBuffer(&sql);
623634
}
624635

625636
/*

0 commit comments

Comments
 (0)