Thread: Code bug or doc bug?

Code bug or doc bug?

From
Josh Berkus
Date:
Folks,

Quoth our docs
(http://www.postgresql.org/docs/9.3/static/sql-alterdatabase.html):

"The fourth form changes the default tablespace of the database. Only
the database owner or a superuser can do this; you must also have create
privilege for the new tablespace. This command physically moves any
tables or indexes in the database's old default tablespace to the new
tablespace. Note that tables and indexes in non-default tablespaces are
not affected."

Yet:

jberkus=# alter database phc set tablespace ssd;
ERROR:  some relations of database "phc" are already in tablespace "ssd"
HINT:  You must move them back to the database's default tablespace
before using this command.

Aside from being a stupid limitation (I need to copy the tables back to
the old tablespace so that I can recopy them to the new one?), the above
seems to be in direct contradiction to the docs.

-- 
Josh Berkus
PostgreSQL Experts Inc.
http://pgexperts.com



Re: Code bug or doc bug?

From
Robert Haas
Date:
On Sun, Aug 24, 2014 at 6:26 PM, Josh Berkus <josh@agliodbs.com> wrote:
> Quoth our docs
> (http://www.postgresql.org/docs/9.3/static/sql-alterdatabase.html):
>
> "The fourth form changes the default tablespace of the database. Only
> the database owner or a superuser can do this; you must also have create
> privilege for the new tablespace. This command physically moves any
> tables or indexes in the database's old default tablespace to the new
> tablespace. Note that tables and indexes in non-default tablespaces are
> not affected."
>
> Yet:
>
> jberkus=# alter database phc set tablespace ssd;
> ERROR:  some relations of database "phc" are already in tablespace "ssd"
> HINT:  You must move them back to the database's default tablespace
> before using this command.
>
> Aside from being a stupid limitation (I need to copy the tables back to
> the old tablespace so that I can recopy them to the new one?), the above
> seems to be in direct contradiction to the docs.

I think that it works OK to move objects from tablespace A to table B
while there are also objects in tablespace C, where B != C, but not to
move objects from tablespace A to tablespace B while there are already
objects in tablespace B.  So I think the documentation is right as far
as it goes, but there's an undocumented limitation there.

The reasons for the limitation are:

1. We can't move a database while there are users connected to it.
This means that we can't modify any of the data in the database in the
process of relocating it.  In particular, we can't update it's copy of
pg_class.

2. By convention, pg_class.reltablespace = 0 when the relation is in
the database's default tablespace, and only contains a non-zero OID
when the relation is in some other tablespace.  This is what lets this
feature work at all: the pg_class.reltablespace value for every
relation we're moving is guaranteed to be 0 before the move, and is
still correctly valued as 0 after the move.  But it also means there
can't be any relations from that database in the new tablespace,
because any such relations would need pg_class.reltablespace to get
updated from the OID of that tablespace to 0.

I don't see any easy way to lift this limitation.  If it were possible
to move a database while users are connected to it, then of course you
could connect to the database to move it and update pg_class, but
you'd have to take an exclusive lock on every relation in the database
simultaneously, which might blow out the lock table, deadlock against
other sessions, and other messy things.

Another idea is to have a command that you can run, while connected to
a particular database, that updates the default tablespace for that
database without actually moving any data on disk - i.e. it sets
pg_database.dattablespace, and then updates every pg_class row where
reltablespace = 0 to the old default tablespace, and pg_class row
where reltablespace = the new tablespace ID to 0.  Then you can move
individual relations afterwards if you feel like it.  But that might
still require a lot of locks, and I think we also have a limitation
that some relations (the mapped ones?) have to be in the database's
default tablespace, which obviously wouldn't work here.

So it's a tricky problem.

-- 
Robert Haas
EnterpriseDB: http://www.enterprisedb.com
The Enterprise PostgreSQL Company



Re: Code bug or doc bug?

From
Bruce Momjian
Date:
On Wed, Aug 27, 2014 at 09:05:41AM -0400, Robert Haas wrote:
> Another idea is to have a command that you can run, while connected to
> a particular database, that updates the default tablespace for that
> database without actually moving any data on disk - i.e. it sets
> pg_database.dattablespace, and then updates every pg_class row where
> reltablespace = 0 to the old default tablespace, and pg_class row
> where reltablespace = the new tablespace ID to 0.  Then you can move
> individual relations afterwards if you feel like it.  But that might
> still require a lot of locks, and I think we also have a limitation
> that some relations (the mapped ones?) have to be in the database's
> default tablespace, which obviously wouldn't work here.
> 
> So it's a tricky problem.

Is there a doc patch to make here?

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + Everyone has their own god. +



Re: Code bug or doc bug?

From
David G Johnston
Date:
Bruce Momjian wrote
> On Wed, Aug 27, 2014 at 09:05:41AM -0400, Robert Haas wrote:
>> Another idea is to have a command that you can run, while connected to
>> a particular database, that updates the default tablespace for that
>> database without actually moving any data on disk - i.e. it sets
>> pg_database.dattablespace, and then updates every pg_class row where
>> reltablespace = 0 to the old default tablespace, and pg_class row
>> where reltablespace = the new tablespace ID to 0.  Then you can move
>> individual relations afterwards if you feel like it.  But that might
>> still require a lot of locks, and I think we also have a limitation
>> that some relations (the mapped ones?) have to be in the database's
>> default tablespace, which obviously wouldn't work here.
>> 
>> So it's a tricky problem.
> 
> Is there a doc patch to make here?

1. Last sentence change suggestion: "The target tablespace must be empty."

2. Based on Robert's comments it sounds like a "You cannot change the
default tablespace of the current database." comment should be added as
well.

Side note: I have no clue what the "mapped relations" Robert refers to
are...

If the locking problem is unsolvable, which seems to be the only realistic
reason why updating pg_class cannot be done somewhere in the process, could
we make it so that the same physical tablespace location can have multiple
pointers?  The problem here would be that a subsequent move would only grab
those relations that are in the current tablespace by default and would
leave the ones that were present originally - unless they get moved in the
interim to the default tablespace (in this case by changing their oid to 0
manually first).

David J.




--
View this message in context: http://postgresql.1045698.n5.nabble.com/Code-bug-or-doc-bug-tp5816052p5816550.html
Sent from the PostgreSQL - hackers mailing list archive at Nabble.com.



Re: Code bug or doc bug?

From
Bruce Momjian
Date:
On Wed, Aug 27, 2014 at 06:39:21AM -0700, David G Johnston wrote:
> > Is there a doc patch to make here?
>
> 1. Last sentence change suggestion: "The target tablespace must be empty."
>
> 2. Based on Robert's comments it sounds like a "You cannot change the
> default tablespace of the current database." comment should be added as
> well.
>
> Side note: I have no clue what the "mapped relations" Robert refers to
> are...

I have created the attached doc patch for this.  Should we backpatch
this through 9.0, or just 9.4?

--
  Bruce Momjian  <bruce@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + Everyone has their own god. +

Attachment

Re: Code bug or doc bug?

From
Bruce Momjian
Date:
On Mon, Oct 13, 2014 at 12:17:54PM -0400, Bruce Momjian wrote:
> On Wed, Aug 27, 2014 at 06:39:21AM -0700, David G Johnston wrote:
> > > Is there a doc patch to make here?
> > 
> > 1. Last sentence change suggestion: "The target tablespace must be empty."
> > 
> > 2. Based on Robert's comments it sounds like a "You cannot change the
> > default tablespace of the current database." comment should be added as
> > well.
> > 
> > Side note: I have no clue what the "mapped relations" Robert refers to
> > are...
> 
> I have created the attached doc patch for this.  Should we backpatch
> this through 9.0, or just 9.4?

Applied.

--  Bruce Momjian  <bruce@momjian.us>        http://momjian.us EnterpriseDB
http://enterprisedb.com
 + Everyone has their own god. +