pg.ddx.io  pgsql-hackers@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Oleg Tkachenko <oatkachenko@gmail.com>
To: pgsql-hackers@lists.postgresql.org
Subject: [BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables
Date: Fri, 14 Nov 2025 20:43:31 +0100
Message-ID: <00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com> (raw)

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



Attachments:

bug_truncation_block_length.patch (application/octet-stream, 548B) download diff --git a/src/backend/backup/basebackup_incremental.c b/src/backend/backup/basebackup_incremental.c index ceec1f44312..7c8138e0386 100644 --- a/src/backend/backup/basebackup_incremental.c +++ b/src/backend/backup/basebackup_incremental.c @@ -854,7 +854,7 @@ GetFileBackupMethod(IncrementalBackupInfo *ib, const char *path, { unsigned relative_limit = limit_block - segno * RELSEG_SIZE; - if (*truncation_block_length < relative_limit) + if (*truncation_block_length > relative_limit) *truncation_block_length = relative_limit; }

view thread (19+ messages)  latest in thread

Message-ID: <00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com>
Permalink:  ../00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com/
Also on:    postgresql.org/message-id/00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-hackers@postgresql.org
  Cc: oatkachenko@gmail.com, pgsql-hackers@lists.postgresql.org
  Subject: Re: [BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables
  In-Reply-To: <00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox