]> granicus.if.org Git - postgresql/commitdiff
Fix relpersistence setting in reindex_index
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 17 Nov 2014 14:23:35 +0000 (11:23 -0300)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 17 Nov 2014 14:23:35 +0000 (11:23 -0300)
Buildfarm members with CLOBBER_CACHE_ALWAYS advised us that commit
85b506bbfc2937 was mistaken in setting the relpersistence value of the
index directly in the relcache entry, within reindex_index.  The reason
for the failure is that an invalidation message that comes after mucking
with the relcache entry directly, but before writing it to the catalogs,
would cause the entry to become rebuilt in place from catalogs with the
old contents, losing the update.

Fix by passing the correct persistence value to
RelationSetNewRelfilenode instead; this routine also writes the updated
tuple to pg_class, avoiding the problem.  Suggested by Tom Lane.

src/backend/catalog/index.c
src/backend/commands/sequence.c
src/backend/commands/tablecmds.c
src/backend/utils/cache/relcache.c
src/include/utils/relcache.h

index b57aa95fafd49b6983af6e4424bf38083a54eabd..844d413adce0addb1be3bace4b7b33f1a6cc596b 100644 (file)
@@ -3191,11 +3191,8 @@ reindex_index(Oid indexId, bool skip_constraint_checks, char persistence)
                        indexInfo->ii_ExclusionStrats = NULL;
                }
 
-               /* Set the relpersistence of the new index */
-               iRel->rd_rel->relpersistence = persistence;
-
                /* We'll build a new physical relation for the index */
-               RelationSetNewRelfilenode(iRel, InvalidTransactionId,
+               RelationSetNewRelfilenode(iRel, persistence, InvalidTransactionId,
                                                                  InvalidMultiXactId);
 
                /* Initialize the index and rebuild */
index e5f7765d556065bc9e293a8aca7530c64095b065..cb8b27a93c0ee439d66eafd44e8243fa72156654 100644 (file)
@@ -303,8 +303,8 @@ ResetSequence(Oid seq_relid)
         * sequence's relfrozenxid at 0, since it won't contain any unfrozen XIDs.
         * Same with relminmxid, since a sequence will never contain multixacts.
         */
-       RelationSetNewRelfilenode(seq_rel, InvalidTransactionId,
-                                                         InvalidMultiXactId);
+       RelationSetNewRelfilenode(seq_rel, seq_rel->rd_rel->relpersistence,
+                                                         InvalidTransactionId, InvalidMultiXactId);
 
        /*
         * Insert the modified tuple into the new storage file.
index 093224f4e644875ebed72b51f12b247031575df9..56294552e715c8bb1516b7055e2c9c0b19355dba 100644 (file)
@@ -1196,7 +1196,8 @@ ExecuteTruncate(TruncateStmt *stmt)
                         * as the relfilenode value. The old storage file is scheduled for
                         * deletion at commit.
                         */
-                       RelationSetNewRelfilenode(rel, RecentXmin, minmulti);
+                       RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
+                                                                         RecentXmin, minmulti);
                        if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
                                heap_create_init_fork(rel);
 
@@ -1209,7 +1210,8 @@ ExecuteTruncate(TruncateStmt *stmt)
                        if (OidIsValid(toast_relid))
                        {
                                rel = relation_open(toast_relid, AccessExclusiveLock);
-                               RelationSetNewRelfilenode(rel, RecentXmin, minmulti);
+                               RelationSetNewRelfilenode(rel, rel->rd_rel->relpersistence,
+                                                                                 RecentXmin, minmulti);
                                if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
                                        heap_create_init_fork(rel);
                                heap_close(rel, NoLock);
index 2250c56d28b219c3acfa5f1c9aa12b9e1b1db23d..c80ef3c6f899ac01a04f3c97ea592fcdf381b91e 100644 (file)
@@ -3005,10 +3005,14 @@ RelationBuildLocalRelation(const char *relname,
  * The relation is marked with relfrozenxid = freezeXid (InvalidTransactionId
  * must be passed for indexes and sequences).  This should be a lower bound on
  * the XIDs that will be put into the new relation contents.
+ *
+ * The new filenode's persistence is set to the given value.  This is useful
+ * for the cases that are changing the relation's persistence; other callers
+ * need to pass the original relpersistence value.
  */
 void
-RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid,
-                                                 MultiXactId minmulti)
+RelationSetNewRelfilenode(Relation relation, char persistence,
+                                                 TransactionId freezeXid, MultiXactId minmulti)
 {
        Oid                     newrelfilenode;
        RelFileNodeBackend newrnode;
@@ -3025,7 +3029,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid,
 
        /* Allocate a new relfilenode */
        newrelfilenode = GetNewRelFileNode(relation->rd_rel->reltablespace, NULL,
-                                                                          relation->rd_rel->relpersistence);
+                                                                          persistence);
 
        /*
         * Get a writable copy of the pg_class tuple for the given relation.
@@ -3048,7 +3052,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid,
        newrnode.node = relation->rd_node;
        newrnode.node.relNode = newrelfilenode;
        newrnode.backend = relation->rd_backend;
-       RelationCreateStorage(newrnode.node, relation->rd_rel->relpersistence);
+       RelationCreateStorage(newrnode.node, persistence);
        smgrclosenode(newrnode);
 
        /*
@@ -3078,7 +3082,7 @@ RelationSetNewRelfilenode(Relation relation, TransactionId freezeXid,
        }
        classform->relfrozenxid = freezeXid;
        classform->relminmxid = minmulti;
-       classform->relpersistence = relation->rd_rel->relpersistence;
+       classform->relpersistence = persistence;
 
        simple_heap_update(pg_class, &tuple->t_self, tuple);
        CatalogUpdateIndexes(pg_class, tuple);
index e4ca70f1404c77ba12e47b01d073e3a1cd106f10..35f2a087e5e5a8705238a1b2f4e77b1afec360e1 100644 (file)
@@ -95,7 +95,7 @@ extern Relation RelationBuildLocalRelation(const char *relname,
 /*
  * Routine to manage assignment of new relfilenode to a relation
  */
-extern void RelationSetNewRelfilenode(Relation relation,
+extern void RelationSetNewRelfilenode(Relation relation, char persistence,
                                                  TransactionId freezeXid, MultiXactId minmulti);
 
 /*