Re: REINDEX INDEX results in a crash for an index of pg_class since 9.6
Andres Freund <andres@anarazel.de>
From: Andres Freund <andres@anarazel.de>
To: Tom Lane <tgl@sss.pgh.pa.us>
Cc: Michael Paquier <michael@paquier.xyz>, Postgres hackers <pgsql-hackers@lists.postgresql.org>
Date: 2019-05-02T02:19:13Z
Lists: pgsql-hackers
Hi,
On 2019-05-01 22:01:53 -0400, Tom Lane wrote:
> Andres Freund <andres@anarazel.de> writes:
> > Well, as I said before, I think hiding the to-be-rebuilt index from the
> > list of indexes is dangerous too - if somebody added an actual
> > CatalogUpdate/Insert (rather than inplace_update) anywhere along the
> > index_build() path, we'd not get an assertion failure anymore, but just
> > an index without the new entry. And given the fragility with HOT hiding
> > that a lot of the time, that seems dangerous to me.
>
> I think that argument is pretty pointless considering that "REINDEX TABLE
> pg_class" does it this way, and that code is nearly old enough to
> vote.
IMO the reindex_relation() case isn't comparable. By my read the main
purpose there is to prevent inserting into not-yet-rebuilt indexes. The
relevant comment says:
* .... If we are processing pg_class itself, we want to make sure
* that the updates do not try to insert index entries into indexes we
* have not processed yet. (When we are trying to recover from corrupted
* indexes, that could easily cause a crash.)
Note the *not processed yet* bit. That's *not* comparable logic to
hiding the index that *already* has been rebuilt, in the middle of
reindex_index(). Yes, the way reindex_relation() is currently coded,
the RelationSetIndexList() *also* hides the already rebuilt index, but
that's hard for reindex_relation() to avoid, because it's outside of
reindex_index().
> + * If we are doing one index for reindex_relation, then we will find that
> + * the index is already not present in the index list. In that case we
> + * don't have to do anything to the index list here, which we mark by
> + * clearing is_pg_class.
> */
> - RelationSetNewRelfilenode(iRel, persistence);
> + is_pg_class = (RelationGetRelid(heapRelation) == RelationRelationId);
> + if (is_pg_class)
> + {
> + allIndexIds = RelationGetIndexList(heapRelation);
> + if (list_member_oid(allIndexIds, indexId))
> + {
> + otherIndexIds = list_delete_oid(list_copy(allIndexIds), indexId);
> + /* Ensure rd_indexattr is valid; see comments for RelationSetIndexList */
> + (void) RelationGetIndexAttrBitmap(heapRelation, INDEX_ATTR_BITMAP_ALL);
> + }
> + else
> + is_pg_class = false;
> + }
That's not pretty either :(
Greetings,
Andres Freund
Commits
-
Remove reindex_catalog test from test schedules.
- 5997a8f4d747 12.0 landed
- 70200d0d7402 9.4.22 landed
- 8439589bc7e7 9.5.17 landed
- 55eebb80005c 9.6.13 landed
- 443ca97956ee 10.8 landed
- 60c2951e1bab 11.3 landed
-
Remove RelationSetIndexList().
- f884dca4959f 12.0 landed
-
Fix reindexing of pg_class indexes some more.
- 5f8e84ff47ff 9.4.22 landed
- f912d7dec293 12.0 landed
- d18ef690509f 9.5.17 landed
- 727c155cfbfb 11.3 landed
- 2bb1adfacdf1 9.6.13 landed
- 18138066ff36 10.8 landed
-
Run catalog reindexing test from 3dbb317d32 serially, to avoid deadlocks.
- ad791802831e 10.8 landed
- 8e955f212089 9.6.13 landed
- 856bc0c612be 9.4.22 landed
- 809c9b48f4bd 12.0 landed
- 63c6a24ae4d6 11.3 landed
- 3630c6bfad94 9.5.17 landed
-
Fix potential assertion failure when reindexing a pg_class index.
- e7418f89f17a 9.4.22 landed
- 670a492c5f1b 9.5.17 landed
- 17126e0892cb 9.6.13 landed
- f495b65a5659 10.8 landed
- 14323493dd53 11.3 landed
- 3dbb317d32f4 12.0 landed
-
Fix several recently introduced issues around handling new relation forks.
- 5c1560606dc4 12.0 landed
-
Avoid VACUUM FULL altogether in initdb.
- 01e386a32554 9.6.0 cited
-
Introduce replication progress tracking infrastructure.
- 5aa2350426c4 9.5.0 cited
-
initdb: remove unnecessary VACUUM FULL
- ed7b3b3811c5 9.5.0 cited