| From: | Alexandre Felipe <o(dot)alexandre(dot)felipe(at)gmail(dot)com> |
|---|---|
| To: | PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | BUG #19686: Rolling back SET TABLESPACE |
| Date: | 2026-09-16 22:06:34 |
| Message-ID: | CAE8JnxP+Ubdj-kaxfgNt=3_FzD3GgOc3gEvPAvrXKfgTgH2q5w@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
This patchset addresses the issue reported on the pgsql-bugs [1]
The root cause is that after the relation files are copied to a new
tablespace queries
update the index in place but the heap is updated only in the tablespace
copy. If
the transaction is rolled back, the index and the heap becomes inconsistent.
First I tried to fix the crash, easy for btree, manageable for hash, but
for GiST that
would not be feasible, AFAIK would have to perform array searches possibly
over
multiple pages. Later thinking about this I noticed something I didn't
realise on my
first read.
Even without inserting duplicates, and no crashes, it can produce incorrect
results.
SET enable_seqscan = off;
SET enable_bitmapscan = off;
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;
INSERT INTO t VALUES (0); -- this adds (0, 1) | 0 to the index in the ts
copy
ROLLBACK;
INSERT INTO t VALUES (41); -- this adds (0, 1) | 41 in the default
tablespace
SELECT ctid, a FROM t WHERE a = 0;
ctid | a
-------+----
(0,1) | 41
(1 row)
So, I decided to fix the root cause: modifying a non-durable copy of the
file.
I thought it would be way harder, but the code was architected well enough
that I could save a list of deferred copies, and keep modifying the the
table
in place. If the transaction is rolled back all the tuples in the index
will have
its (possibly dead) in the heap, effectively reserving those TID, this
prevents
both the insertion of duplicates, and the resuscitation of dead tuples by
later changes.
[1]
https://www.postgresql.org/message-id/19686-30f4da834585129f%40postgresql.org
| Attachment | Content-Type | Size |
|---|---|---|
| v1-0001-nbtree-skip-insertion-of-existing-tuples.patch | application/octet-stream | 6.2 KB |
| v1-0002-logging-and-testcase.patch | application/octet-stream | 10.6 KB |
| v1-0004-establish-expected-tablespace.out.patch | application/octet-stream | 7.0 KB |
| v1-0003-fix-deferred-relation-copy.patch | application/octet-stream | 9.3 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Alexander Korotkov | 2026-09-16 22:30:27 | Re: Improve WAIT FOR read-your-writes consistency doc |
| Previous Message | Alexander Korotkov | 2026-09-16 21:59:53 | Re: WAIT FOR NO_THROW option could use some documentation |