Fix race condition in statext_store().
authorTom Lane
Tue, 31 Mar 2020 21:06:22 +0000 (17:06 -0400)
committerTom Lane
Tue, 31 Mar 2020 21:06:22 +0000 (17:06 -0400)
Must hold some lock on the pg_statistic_ext_data catalog *before*
we look up the tuple we aim to replace.  Otherwise a concurrent
VACUUM FULL or similar operation could move it to a different TID,
leaving us trying to replace the wrong tuple.

Back-patch to v12 where this got broken.

Credit goes to Dean Rasheed; I'm just doing the clerical work.

Discussion: https://postgr.es/m/CAEZATCU0zHMDiQV0g8P2U+YSP9C1idUPrn79DajsbonwkN0xvQ@mail.gmail.com

src/backend/statistics/extended_stats.c

index 4516c97f4066ac5cd87ae8b43b46b68791e77fc4..d8e5150023257e3e6c1a697f4c6f76eb3dfee362 100644 (file)
@@ -322,12 +322,14 @@ statext_store(Oid statOid,
              MVNDistinct *ndistinct, MVDependencies *dependencies,
              MCVList *mcv, VacAttrStats **stats)
 {
+   Relation    pg_stextdata;
    HeapTuple   stup,
                oldtup;
    Datum       values[Natts_pg_statistic_ext_data];
    bool        nulls[Natts_pg_statistic_ext_data];
    bool        replaces[Natts_pg_statistic_ext_data];
-   Relation    pg_stextdata;
+
+   pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock);
 
    memset(nulls, true, sizeof(nulls));
    memset(replaces, false, sizeof(replaces));
@@ -371,8 +373,6 @@ statext_store(Oid statOid,
        elog(ERROR, "cache lookup failed for statistics object %u", statOid);
 
    /* replace it */
-   pg_stextdata = table_open(StatisticExtDataRelationId, RowExclusiveLock);
-
    stup = heap_modify_tuple(oldtup,
                             RelationGetDescr(pg_stextdata),
                             values,