| From: | Oleg Tkachenko <oatkachenko(at)gmail(dot)com> |
|---|---|
| To: | pgsql-hackers(at)lists(dot)postgresql(dot)org |
| Subject: | [BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables |
| Date: | 2025-11-14 19:43:31 |
| Message-ID: | 00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com |
| Views: | Whole Thread | Raw Message | Download mbox | Resend email |
| Thread: | |
| Lists: | pgsql-hackers |
Hello PostgreSQL developers,
I’ve encountered a bug in the incremental backup feature that prevents restoration of backups containing relations larger than 1 GB that were vacuum-truncated.
Problem Description
When taking incremental backups of relations that span multiple segments, if the relation is truncated during VACUUM (after the base backup but before the incremental one), pg_combinebackup fails with:
```
file "%s" has truncation block length %u in excess of segment size %u
```
pg_basebackup itself completes without errors, but the resulting incremental backup cannot be restored.
Root Cause
In segmented relations, a VACUUM that truncates blocks sets a limit_block in the WAL summary. The incremental restore logic miscalculates truncation_block_length when processing segment 0…N, because it compares the segment-local size with a relation-wide limit.
In src/backend/backup/basebackup_incremental.c:
```
*truncation_block_length = size / BLCKSZ;
if (BlockNumberIsValid(limit_block))
{
unsigned relative_limit = limit_block - segno * RELSEG_SIZE;
if (*truncation_block_length < relative_limit) /* ← problematic */
*truncation_block_length = relative_limit;
}
```
For example, if limit_block lies in segment 10, then relative_limit will be roughly 9 * RELSEG_SIZE while processing segment 0. This forces truncation_block_length far beyond the actual segment size, leading to a segment length larger than RELSEG_SIZE and eventually the restore error.
Reproduction Steps
Create a table larger than 1 GB (multiple segments).
Take a full base backup.
Delete rows that occupy the end of the relation.
Run VACUUM (VERBOSE, TRUNCATE) to ensure blocks are removed.
(optional) Confirm that the WAL summary includes a limit entry for the relation.
Take an incremental backup with pg_basebackup.
Attempt to restore using pg_combinebackup.
Observe the truncation block length error.
Patch
A patch correcting this logic is attached, and I’m happy to provide additional details or revisions if helpful.
Best regards,
Oleg Tkachenko

| From | Date | Subject | |
|---|---|---|---|
| Next Message | Nathan Bossart | 2025-11-14 19:46:48 | Re: Uncommented GUC in postgresql.conf.sample |
| Previous Message | Tom Lane | 2025-11-14 19:37:48 | Re: Compile error on the aarch64 platform: Missing asm/hwcap.h |