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
Patch A patch correcting this logic is attached, and I’m happy to provide additional details or revisions if helpful. Best regards, Oleg Tkachenko |
bug_truncation_block_length.patch
Description: Binary data
