Re: Allow CLUSTER, VACUUM FULL and REINDEX to change tablespace on the fly - Mailing list pgsql-hackers

From Alexey Kondratov
Subject Re: Allow CLUSTER, VACUUM FULL and REINDEX to change tablespace on the fly
Date
Msg-id c36e51a07183b95ddd287be4ee4cfbbd@postgrespro.ru
Whole thread Raw
In response to Re: Allow CLUSTER, VACUUM FULL and REINDEX to change tablespace on the fly  (Alexey Kondratov <a.kondratov@postgrespro.ru>)
List pgsql-hackers
On 2021-01-26 09:58, Michael Paquier wrote:
> On Mon, Jan 25, 2021 at 11:11:38PM +0300, Alexey Kondratov wrote:
>> I updated comment with CCI info, did pgindent run and renamed new 
>> function
>> to SetRelationTableSpace(). New patch is attached.
>> 
>> [...]
>> 
>> Yeah, all these checks we complicated from the beginning. I will try 
>> to find
>> a better place tomorrow or put more info into the comments at least.
> 
> I was reviewing that, and I think that we can do a better
> consolidation on several points that will also help the features
> discussed on this thread for VACUUM, CLUSTER and REINDEX.
> 
> If you look closely, ATExecSetTableSpace() uses the same logic as the
> code modified here to check if a relation can be moved to a new
> tablespace, with extra checks for mapped relations,
> GLOBALTABLESPACE_OID or if attempting to manipulate a temp relation
> from another session.  There are two differences though:
> - Custom actions are taken between the phase where we check if a
> relation can be moved to a new tablespace, and the update of
> pg_class.
> - ATExecSetTableSpace() needs to be able to set a given relation
> relfilenode on top of reltablespace, the newly-created one.
> 
> So I think that the heart of the problem is made of two things here:
> - We should have one common routine for the existing code paths and
> the new code paths able to check if a tablespace move can be done or
> not.  The case of a cluster, reindex or vacuum on a list of relations
> extracted from pg_class would still require a different handling
> as incorrect relations have to be skipped, but the case of individual
> relations can reuse the refactoring pieces done here
> (see CheckRelationTableSpaceMove() in the attached).
> - We need to have a second routine able to update reltablespace and
> optionally relfilenode for a given relation's pg_class entry, once the
> caller has made sure that CheckRelationTableSpaceMove() validates a
> tablespace move.
> 

I think that I got your idea. One comment:

+bool
+CheckRelationTableSpaceMove(Relation rel, Oid newTableSpaceId)
+{
+    Oid            oldTableSpaceId;
+    Oid            reloid = RelationGetRelid(rel);
+
+    /*
+     * No work if no change in tablespace.  Note that MyDatabaseTableSpace
+     * is stored as 0.
+     */
+    oldTableSpaceId = rel->rd_rel->reltablespace;
+    if (newTableSpaceId == oldTableSpaceId ||
+        (newTableSpaceId == MyDatabaseTableSpace && oldTableSpaceId == 0))
+    {
+        InvokeObjectPostAlterHook(RelationRelationId, reloid, 0);
+        return false;
+    }

CheckRelationTableSpaceMove() does not feel like a right place for 
invoking post alter hooks. It is intended only to check for tablespace 
change possibility. Anyway, ATExecSetTableSpace() and 
ATExecSetTableSpaceNoStorage() already do that in the no-op case.

> Please note that was a bug in your previous patch 0002: shared
> dependencies need to be registered if reltablespace is updated of
> course, but also iff the relation has no physical storage.  So
> changeDependencyOnTablespace() requires a check based on
> RELKIND_HAS_STORAGE(), or REINDEX would have registered shared
> dependencies even for relations with storage, something we don't
> want per the recent work done by Alvaro in ebfe2db.
> 

Yes, thanks.

I have removed this InvokeObjectPostAlterHook() from your 0001 and made 
0002 to work on top of it. I think that now it should look closer to 
what you described above.

In the new 0002 I moved ACL check to the upper level, i.e. 
ExecReindex(), and removed expensive text generation in test. Not 
touched yet some of your previously raised concerns. Also, you made 
SetRelationTableSpace() to accept Relation instead of Oid, so now we 
have to open/close indexes in the ReindexPartitions(), I am not sure 
that I use proper locking there, but it works.


Regards
-- 
Alexey Kondratov

Postgres Professional https://www.postgrespro.com
Russian Postgres Company
Attachment

pgsql-hackers by date:

Previous
From: Justin Pryzby
Date:
Subject: wiki:PostgreSQL_14_Open_Items
Next
From: Heikki Linnakangas
Date:
Subject: Re: Online checksums patch - once again