[BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables

Поиск
Список
Период
Сортировка
От Oleg Tkachenko
Тема [BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables
Дата
Msg-id 00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com
обсуждение исходный текст
Список 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

  1. Create a table larger than 1 GB (multiple segments).

  2. Take a full base backup.

  3. Delete rows that occupy the end of the relation.

  4. Run VACUUM (VERBOSE, TRUNCATE) to ensure blocks are removed.

  5. (optional) Confirm that the WAL summary includes a limit entry for the relation.

  6. Take an incremental backup with pg_basebackup.

  7. Attempt to restore using pg_combinebackup.

  8. 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



Вложения

В списке pgsql-hackers по дате отправления: