Re: Reject COPY TO of unlogged relations during recovery

From: Jim Jones <jim(dot)jones(at)uni-muenster(dot)de>
To: Zsolt Parragi <zsolt(dot)parragi(at)percona(dot)com>
Cc: pgsql-hackers(at)lists(dot)postgresql(dot)org
Subject: Re: Reject COPY TO of unlogged relations during recovery
Date: 2026-10-16 07:34:51
Message-ID: c4130a17-a5d8-490f-b645-536d352c8405@uni-muenster.de
Views: Whole Thread | Raw Message | Download mbox | Resend email
Thread:
Lists: pgsql-hackers

Hi Zsolt

On 15/10/2026 23:38, Zsolt Parragi wrote:
> Claude pointed out that a few contrib modules are also affected
> (pgstattuple, pg_visibility, pageinspect and pgrowlocks)
>
> I think the location is right for the COPY TO case, but maybe it would
> be the best to handle all locations in the same patch(set)?

The fix itself here shouldn't be too difficult, but I anticipate some
questions on "how" unlogged tables should be treated, for instance
amcheck seems to simply skips it:

postgres=# set client_min_messages to debug1;
SET
postgres=# select * from verify_heapam('ut');
DEBUG: cannot verify unlogged relation "ut" during recovery, skipping
blkno | offnum | attnum | msg
-------+--------+--------+-----
(0 rows)

So I am not sure how the mentioned contrib modules should behave. But I
agree that anything is better than the current error message:

postgres=# select * from pgrowlocks('ut');
ERROR: could not open file "base/5/16410": No such file or directory

That said, I would be in favour of creating a separate patch for the
contrib modules. WDYT?

>
> + foreach_oid(child, children)
> + {
> + if (get_rel_persistence(child) != RELPERSISTENCE_PERMANENT)
>
> Can we put this check in the existing loop above? And maybe the error
> detail could also name the specific relation?

I moved the check to the existing loop and added the relation name to
errdetail on partition tables:

== primary ==

psql (20devel)
Type "help" for help.

postgres=# create unlogged table ut as select 1 ;
SELECT 1
postgres=# create table pt (a int) partition by range (a);
CREATE TABLE
postgres=# create unlogged table pt_p1 partition of pt for values from
(0) to (10);
CREATE TABLE

== standby ==

psql (20devel)
Type "help" for help.

postgres=# copy ut to stdout;
ERROR: cannot access temporary or unlogged relations during recovery
postgres=# copy pt to stdout;
ERROR: cannot access temporary or unlogged relations during recovery
DETAIL: Partition "pt_p1" is an unlogged table in partitioned table "pt".

I didn't add the relation name to non-partitioned unlogged tables to
make it consistent with the errmsg of a select:

postgres=# select * from ut;
ERROR: cannot access temporary or unlogged relations during recovery

PFA v2.

Thanks for the review!

Best, Jim

Attachment Content-Type Size
v2-0001-Reject-COPY-TO-of-unlogged-tables-during-recovery.patch text/x-patch 4.5 KB

In response to

Browse pgsql-hackers by date

  From Date Subject
Next Message Bertrand Drouvot 2026-10-16 07:45:26 Use a bulk-write buffer access strategy for TOAST inserts
Previous Message Álvaro Herrera 2026-10-16 07:32:16 Re: ATTACH PARTITION cost grows linearly with pg_constraint size (seqscan in CloneFkReferenced), much worse since not-null constraints are in pg_constraint (PG 18)