Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vJzi8-00BCmD-1s for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Nov 2025 19:43:55 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1vJzi6-007mwV-0X for pgsql-hackers@arkaria.postgresql.org; Fri, 14 Nov 2025 19:43:54 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.96) (envelope-from ) id 1vJzi5-007mwN-2i for pgsql-hackers@lists.postgresql.org; Fri, 14 Nov 2025 19:43:53 +0000 Received: from mail-ed1-x536.google.com ([2a00:1450:4864:20::536]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.96) (envelope-from ) id 1vJzi3-007lsm-0h for pgsql-hackers@lists.postgresql.org; Fri, 14 Nov 2025 19:43:53 +0000 Received: by mail-ed1-x536.google.com with SMTP id 4fb4d7f45d1cf-640d0ec9651so3913148a12.3 for ; Fri, 14 Nov 2025 11:43:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1763149424; x=1763754224; darn=lists.postgresql.org; h=to:date:message-id:subject:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=PluGDiFUgi4AQq81R8wEYcmHUdgfSffdltosnL58JYY=; b=Mysyj11XogvjnqwefI8GuTN4Pq4/3z36CGXHPt8kDR19XC2J2+fiw8UR3k8N1O5BQm gfNfxP9Mo/ERb84cAr3CZAMryzwWxqNT6cpMJKu+xUnMScfow/BZddTpMYjN8tnVeFZb 9zts7x8P0k17xvn/Fuo7qWrpDCjR74G1IYWKKuJvKsFsQsAkjQkXooP+0aOzmOlX+h96 mrSK2wWKRx4wvOqTypDm/SZUt313qUfjk7TF+teZVsqJ0IpBBZ5YjfKAf1tfY11lVLHz y2XZ4JqsmzTH18BMOww1ZLkugTXlw/mm86fn6fnbJMQTuuD9ZKJKGsO+oSpbRgSIH3sf Pd/w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763149424; x=1763754224; h=to:date:message-id:subject:mime-version:from:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=PluGDiFUgi4AQq81R8wEYcmHUdgfSffdltosnL58JYY=; b=wleP8CPVOKZnFGAV3RD9Q3Z5lbJlWecziXPj4u0FjbYpjtO6iAGd1UNfYrbaG7N+JD WcbbaLmxyoxbN1OGKIoxx+/3A//8YDLi//gBBmzE3vHEBR3EfPLSK+MT0AW4UQapE1PY 7ld7UFF4sBxIiGP3aE53iF6Quu8rrG8+9iTU5Am31FXEwgeObmk+LLmkq4qpJua3gVXE OaQJmmMsqXnTtiIDZIxYZr0b7hgfIgyvdhGXPj3wYUMePPN+Dd68vB7Ij1DLObdAX4il a5osO97ogf7cORoYI/1PmaJUR8+u8aAq7ErRDmEx+2GN2no63vXjmb8Ed14cXjmXXbq+ n3wQ== X-Gm-Message-State: AOJu0YxbmhO8EmlFIMw91Q7z+lkQb1ffLsT5Uy4rWkS5XQ2jKssrB1rq DxwxpVcKYHyFKlKliJK9UQb/v7R+/gJMGuul4I+lifwCBrnE6s1idT+WI8UYIA== X-Gm-Gg: ASbGncuJyP18OphnoHFKEgBeDGOThxOrt0cJNyrZTY837jh5jNeSPXk42rMs74tlcLA VxOMMyIIEjcEI3PXM2br1Cf6IFKPYEaoIWLZPHOq1B7zjQuhj8rQGoYqyqta46RmadALjnXWyjs /WOyohKcMYnc8ORRCW/T+JixZRwYpm5IzJLzIwqAiyCGGmzBKgRTtQJTXsfWHi/nIhHiYBPZ06X pVWPdU4IqoJzjCXs1utrqEDG3NTSDa8Dxta0D5mYfv2wh1Xdu+RXvGImc8TkypbKIMp1pswMb9j X0bH/CA9Bk6Z+yZlnJkC6K5sByG5BHNwmG0o9MM/U6ISy+ErhdwW+e0Cf0FFYWXs6BRG4EYsa63 VYuRhBhZTT/lnIbk6loV3rrKu1jBtDfHYo0znooVF1MbZ4FiUsdpLSxYFzxqjpr95gYGSJDjVMY JNDFCMl1XviVm/QPzbovRZXQV1x+9BNIVA+f8JpuZISszpmw== X-Google-Smtp-Source: AGHT+IHhT9wvjUgxB+P5obs9RnZkLklHzJzgnP3JZfCXL1wnQu46qaAjODiSRdLuZauSdwx3UfsiYg== X-Received: by 2002:a05:6402:1eca:b0:63c:683c:f9d2 with SMTP id 4fb4d7f45d1cf-64350e21861mr3900279a12.12.1763149424339; Fri, 14 Nov 2025 11:43:44 -0800 (PST) Received: from smtpclient.apple ([2a02:a31a:a49d:1500:9192:ad81:a7fb:baa1]) by smtp.gmail.com with ESMTPSA id 4fb4d7f45d1cf-6433a497080sm4438258a12.19.2025.11.14.11.43.41 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Fri, 14 Nov 2025 11:43:42 -0800 (PST) From: Oleg Tkachenko X-Google-Original-From: Oleg Tkachenko Content-Type: multipart/alternative; boundary="Apple-Mail=_4B96515F-4002-455F-986B-3422F80B2105" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3864.200.81.1.6\)) Subject: [BUG] pg_basebackup produces wrong incremental files after relation truncation in segmented tables Message-Id: <00FEFC88-EA1D-4271-B38F-EB741733A84A@gmail.com> Date: Fri, 14 Nov 2025 20:43:31 +0100 To: pgsql-hackers@lists.postgresql.org X-Mailer: Apple Mail (2.3864.200.81.1.6) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk --Apple-Mail=_4B96515F-4002-455F-986B-3422F80B2105 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 Hello PostgreSQL developers, I=E2=80=99ve 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=E2=80=A6N,= because it compares the segment-local size with a relation-wide limit. In src/backend/backup/basebackup_incremental.c: ``` *truncation_block_length =3D size / BLCKSZ; if (BlockNumberIsValid(limit_block)) { unsigned relative_limit =3D limit_block - segno * RELSEG_SIZE; if (*truncation_block_length < relative_limit) /* =E2=86=90 = problematic */ *truncation_block_length =3D 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=E2=80=99m happy to = provide additional details or revisions if helpful. Best regards, Oleg Tkachenko =EF=BF=BC --Apple-Mail=_4B96515F-4002-455F-986B-3422F80B2105 Content-Type: multipart/mixed; boundary="Apple-Mail=_944BF3FE-A66F-4BB8-9116-23EC8C59BA63" --Apple-Mail=_944BF3FE-A66F-4BB8-9116-23EC8C59BA63 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

Hello PostgreSQL developers,

I=E2=80=99ve 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=E2=80=A6N, because it compares the segment-local size with a = relation-wide limit.

In src/backend/backup/basebackup_incremental.c:

```

*truncation_block_length =3D size / BLCKSZ;

if (BlockNumberIsValid(limit_block))

{

    unsigned = relative_limit =3D limit_block - segno * = RELSEG_SIZE;

  =   if (*truncation_block_length < relative_limit)   /* =E2=86=90= problematic */

  =       *truncation_block_length =3D = 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=E2=80=99m happy to provide = additional details or revisions if helpful.


Best = regards,

Oleg = Tkachenko

= --Apple-Mail=_944BF3FE-A66F-4BB8-9116-23EC8C59BA63 Content-Disposition: attachment; filename=bug_truncation_block_length.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="bug_truncation_block_length.patch" Content-Transfer-Encoding: 7bit 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; } --Apple-Mail=_944BF3FE-A66F-4BB8-9116-23EC8C59BA63 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii



--Apple-Mail=_944BF3FE-A66F-4BB8-9116-23EC8C59BA63-- --Apple-Mail=_4B96515F-4002-455F-986B-3422F80B2105--