| From: | Rui Zhao <zhaorui126(at)gmail(dot)com> |
|---|---|
| To: | Michael Paquier <michael(at)paquier(dot)xyz> |
| Cc: | Bharath Rupireddy <bharath(dot)rupireddyforpostgres(at)gmail(dot)com>, Greg Burd <greg(at)burd(dot)me>, Yugo Nagata <nagata(at)sraoss(dot)co(dot)jp>, PostgreSQL Hackers <pgsql-hackers(at)lists(dot)postgresql(dot)org> |
| Subject: | Re: Support for 8-byte TOAST values, round two |
| Date: | 2026-09-11 17:38:06 |
| Message-ID: | CAHWVJhGkb1n_QSS4M=PKJD5HHcwK3KXpFwVxoRVLzAG3j+2fhQ@mail.gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hi Michael,
v17 applies to master (6a1c1102c4), builds warning-free, and make
check-world passes here. Three small patches attached: 0001 applies to
master, 0002 and 0003 on top of 0005.
1. The 8-byte counter survives standby promotion and crash recovery,
which the tests of cb298616463d do not cover; 0001 adds the standby case
to 004_timeline_switch.pl.
Primary counter set to 4295067296 (2^32 + 100000), base backup, then
20000 values into an oid8 table, so the standby sees the counter only
through XLOG_NEXTOID records. After promotion and 3000 more values,
next_oid is 4295100064; the same after killing the primary with an
immediate shutdown and restarting it. All 23000 values read back equal
on both nodes, chunk_ids 4295067301 to 4295094871, all distinct.
2. pg_upgrade works both ways that matter: a v17 cluster with oid8
tables and the counter past 2^32 comes out usable, and a 16beta2 cluster
comes out with its oid TOAST tables intact and able to add oid8 ones.
v17 to v17: NextOID 4295067406 before and after, then 120 more rows into
an oid8 and an oid table, 120 new distinct IDs each. 16beta2 to v17: an
external and a compressed TOAST table stay oid, reads and inserts work,
verify_heapam() finds nothing, an oid8 table created next to them works,
and a plain dump restores with the same chunk_id types.
3. Logical decoding of oid8 values past 2^32 works, but no test in 0004
would catch it if it broke; 0002 adds one that does.
Publisher and subscriber in one cluster, counter past 2^32, two rows with
9000-byte values, one then updated on a non-TOAST column, one given a
new value: the subscriber ends with the same lengths and md5s, chunk_ids
4295067317 and 4295067319. The toast.sql additions in 0004 run with a
young counter, so their IDs fit in 4 bytes and a chunk_id read as an Oid
still matches. 0002 moves the counter past 2^32 in
006_logical_decoding.pl and decodes one oid8 value; with the chunk_id
read the way it was before v14 the row comes out as
data[text]:unchanged-toast-datum, with v17 it passes.
4. A rewrite after ALTER TABLE SET (toast_value_type) keeps the TOAST
table's type either way, as Bharath concluded from the code.
VACUUM FULL, CLUSTER, REPACK, SET UNLOGGED and SET LOGGED, on an oid
table switched to oid8 and on an oid8 table with IDs past 2^32 switched
to oid: chunk_id type unchanged, 50 of 50 values intact, verify_heapam()
and bt_index_check() clean after each. Only a TOAST table created
afterwards (ADD COLUMN on a table that had none, CREATE TABLE AS) picks
up the new value.
5. For oid8 tables the -o docs are incomplete: a lost pg_control moves
the counter backwards by itself, and the value to set, which the docs
say there is no easy way to find, is one query away. 0003 says so under
-o, and adds that the reloption has to be given on every partition (the
reloptions test checks that a partitioned table rejects it; I checked
that a partition created without it gets an oid TOAST table).
Rare case: pg_control lost, cluster brought back with pg_resetwal -f as
documented, the OID counter comes back as the guess, 10000. On a fresh
cluster with 1000 values in an oid8 table (chunk_ids 16394 to 17393) and
1000 in an oid table, the oid table takes new rows as before and inserts
into the oid8 table fail with
ERROR: duplicate key value violates unique constraint "pg_toast_16384_index"
each failed statement moving the counter by one, so a thousand failures
before it comes back on its own. SELECT max(chunk_id) on the oid8 TOAST
table gave 17393; pg_resetwal -o 17394 put it back to work.
Regards,
Rui
| Attachment | Content-Type | Size |
|---|---|---|
| 0001-Check-that-a-promoted-standby-keeps-the-8-byte-OID-c.patch | application/octet-stream | 2.0 KB |
| 0002-Decode-an-oid8-TOAST-value-with-an-ID-past-2-32.patch | application/octet-stream | 2.5 KB |
| 0003-Document-two-things-about-toast_value_type-oid8.patch | application/octet-stream | 2.6 KB |
| From | Date | Subject | |
|---|---|---|---|
| Next Message | Masahiko Sawada | 2026-09-11 17:56:11 | Re: REPACK (CONCURRENTLY) can crash a logical decoding session |
| Previous Message | Bryan Green | 2026-09-11 17:31:29 | [RFC] An ETW backend for the static probes on Windows |