Re: BUG #19686: Rolling back SET TABLESPACE

From: Manu <manuelreyesbravo(at)gmail(dot)com>
To: Alexandre Felipe <o(dot)alexandre(dot)felipe(at)gmail(dot)com>, pgsql-hackers(at)lists(dot)postgresql(dot)org
Cc: Alexander Lakhin <exclusion(at)gmail(dot)com>, Shihao Zhong <zhong950419(at)gmail(dot)com>
Subject: Re: BUG #19686: Rolling back SET TABLESPACE
Date: 2026-09-27 19:09:53
Message-ID: 179053619396.834181.4343350041923422703@gmail.com
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

I wrote a patch for the same bug before I saw this thread -- thanks to
Shihao for pointing me here. Having read #7312, I think your deferred
copy is the right approach, and better than what I had: it fixes the
root cause without touching the indexes.

> What do you think of this approach?

On performance it looks very good. On a 1M-row table with three indexes
I measured SET TABLESPACE at about 104 ms with #7312 versus about 108 ms
on master -- no measurable overhead, since the indexes are left alone.
(My own patch copies each index to a new relfilenode, which came out
around 1.7x, so #7312 is the better direction and I'm happy to drop mine.)

One thing I ran into while testing: a second SET TABLESPACE in the same
transaction, on a table with indexes, ends up in the wrong tablespace.

SET allow_in_place_tablespaces = true;
CREATE TABLESPACE ts LOCATION '';
CREATE TABLE t (a int);
CREATE INDEX ON t (a);
BEGIN;
ALTER TABLE t SET TABLESPACE ts;
ALTER TABLE t SET TABLESPACE pg_default;
COMMIT;
-- master: t ends up in pg_default; with #7312: t ends up in ts

The second ALTER calls CheckRelationTableSpaceMove() while pg_class still
shows the original tablespace (the first move is deferred), so moving
back to pg_default looks like a no-op and is dropped. The deferred move
probably needs to be visible to a later SET TABLESPACE in the same
transaction.

> 2. Failure to copy the files at the end of transaction [...]

Agreed this one deserves care -- moving the copy into PreCommit means a
full tablespace now fails at commit time rather than during the command.

On 0001: with 0003 in place I couldn't get the new "skip existing tuple"
path to fire in any of my tests, and turning the assertion into a silent
skip also drops a useful corruption check. Could it be removed now?

Happy to help test further.

Manu

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Scott Ray 2026-09-27 19:20:02 Re: pg_xmin_horizon: a system view of everything pinning the xmin horizon
Previous Message Alexandre Felipe 2026-09-27 18:56:06 Re: BUG #19686: Rolling back SET TABLESPACE