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 1wglVN-006Nur-0W for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 15:45:09 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.96) (envelope-from ) id 1wglVM-001UVt-0D for pgsql-hackers@arkaria.postgresql.org; Mon, 06 Jul 2026 15:45:08 +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 1wglVL-001UVV-2D for pgsql-hackers@lists.postgresql.org; Mon, 06 Jul 2026 15:45:07 +0000 Received: from mail-lj1-x22e.google.com ([2a00:1450:4864:20::22e]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.98.2) (envelope-from ) id 1wglVJ-000000025Hw-1y65 for pgsql-hackers@postgresql.org; Mon, 06 Jul 2026 15:45:07 +0000 Received: by mail-lj1-x22e.google.com with SMTP id 38308e7fff4ca-39b011ae0b4so23936601fa.1 for ; Mon, 06 Jul 2026 08:45:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1783352703; cv=none; d=google.com; s=arc-20260327; b=oO9xJqFXye+WQlIaHeMCWEHWjIqELiuHYV7k6EvexOv46UNCh0tgMD97PfYh3WJTLC NH/aUWJGOPP6hjjHsxhwX7x+I15zmmCvzaK75Ky8/h+SOaL8nlF6WLpHJ5un2KHaqwE5 02fF6T2ILkbKHBs7VtpnMh6ZKTfJN4Xo728/LEANm+M0QxksvVXWUJKl1riWl3ZiNtfp IPgQre9qYgIDLHsWn/q0Gb97oLfqi6D47thsKPnEOdcs4U6EKxwBjZW22jC0/lIjJHqa p9FkhzDUMq9r6Cxucq01s2t4MtsKAo2pitTJlY0mn8lFsSiZcxjqHqMMgZh2SCce7jUc VGpg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20260327; h=content-transfer-encoding:cc:to:subject:message-id:date:from :in-reply-to:references:mime-version:dkim-signature; bh=pMMEGWe773SD0kXbeKYFuSfQKGNaimm+7DViKJuqQVo=; fh=l/B4CL5lSscDxGpwJH+1aSjAkK1VZ5a0QHZBRg+X+1o=; b=MP7UWXM5fAqlgfmLLymNmxWDaQOFlAYgVcC/mdwVWyLK54mJ8WZsQVyEw5mkF0vG4y oyq/edQCNSDY81l7pBHw+OElEalev8IAdQSrm5J/0/pVkD83dG6rxW26m4SVt/dDNepz IMSy2l+jJiP+P/YhlEGxL1PcGSj55vOv0FfHAvmEmEtpGEv+dzjdk5PrS2L7jZR5i3KJ g6KMynpHYtDYKwyjtuareKhhm6zPvLLRMxb31N5KxLpgraIMI/vEeOoCYThIk3IcR1hS eldNxSJlFYL07ev7ljefM3Ar1q8I99Y8USAMcLy72aGR5Enc8OMK5soKO9wKbOr3tjkP Uq/Q==; darn=postgresql.org ARC-Authentication-Results: i=1; mx.google.com; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1783352703; x=1783957503; darn=postgresql.org; h=content-transfer-encoding:content-type:cc:to:subject:message-id :date:from:in-reply-to:references:mime-version:from:to:cc:subject :date:message-id:reply-to:content-type; bh=pMMEGWe773SD0kXbeKYFuSfQKGNaimm+7DViKJuqQVo=; b=ptBb5eQu5PWWNkiqh0Z3sNsbRIw/FRVrrz1QdyQU0KEdFkz0u35mdFmry9mhdDC4Hi DhGFsCbZWmoypgIuCe0RKuHvyhEMTwBnCRhhVfkukXj2Vz0PH05GXCakMu4YnLx7urWa HgRW/tQIaOGVTYh8hY0vE/A66TcwABj8vg3SCIXIj4YxVZGAY3gCP4V+5C/LW/v1mgtS 77S7H8/NQ2JaaE4tdz9k9k6Dtx4c7yXm9dYJP9ecdl8d7pC2bC/mcoxYvDlu2EuWjwbk PCTMvRUUCQYCVzfHHDQA8LZZZWdnDgfXJLrts6CFkWmUDNsx0pgrubVLrAYH44D6PuFn wWmA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1783352703; x=1783957503; h=content-transfer-encoding:content-type:cc:to:subject:message-id :date:from:in-reply-to:references:mime-version:x-gm-gg :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to :content-type; bh=pMMEGWe773SD0kXbeKYFuSfQKGNaimm+7DViKJuqQVo=; b=c89Fomglumx7YBKPHmsTU73JX4LGlpTmnUYb0l65mKtvv6vKKwyCCDApFef7T4O6LM ikqKQgfNs8yzw/NJOmwAXEKGnnEBOPsfG9CH/hl2VCoCKzVAl6yVp/m0PuyPFK+izFYu Ym8iuOWBBE17oQe/MVeczE+zsXBsWSuguX8ZpyExJCQaTK7s8337WeqRpKzBYV5teOXh vU7IF8vE0RBvuB7gcHauL2Zjs4LONcI3GDgXIQupUU8W/QTeYsuVcfUvYheWlSFPxa9P XsDEtC9sxQ5xP43yYAz9k6r6c/hjdi/TTakn871dXpYYGZgmpga6mJ02ekM6z3CgsBB3 Kz0Q== X-Gm-Message-State: AOJu0YxLxgEx+5Jw3KmUALkUEFtcrecj4Vo8UyjVeb0aOkLksqlJoLnn fhMm3LGQUFFBn5k3+qk98nZgJKK1tOriTe958fEkDn6cf2diSvSbP+ZTwQr/OTU+HS/yrmXqNLx e82lwKn4dLXTxvwoOEA+MkezuIT5swdk= X-Gm-Gg: AfdE7cnW1pCQq627k+E88NScRHkMpQW2bD+wqIgCIxBAYd9j00QULY9aruxga4P3Kdt aRuK9TguKX3QoITR+LmnhGzIU/kmFN65eKWGh1+s0DHYEhe2DCtlhYiDIdtMoe6mS8wcrpG7UZe jsMusfa+Pba8g+6SwDWxJ5zONGahoHMiH0KgxxYONMCMk/rd4FxZ44TdJKrn9SebOgtijzC+FYu nz0qTFfv+nT9EmlQtJEm8W/sXsHPkRsdULWFVCdRHGkt5CW+x6YZgN2AQGR44O9dTI24zh7WrPq vExfzaa8UjeAjzzY+pJI3+NrjDgecgxY0r90Rf5/ZCqQTwsGUlcTWQn3egofrzTbNA4MTA== X-Received: by 2002:a05:6512:1141:b0:5ae:b9e6:afac with SMTP id 2adb3069b0e04-5b007c07cd9mr169807e87.23.1783352702933; Mon, 06 Jul 2026 08:45:02 -0700 (PDT) MIME-Version: 1.0 References: <1779078055.630771314@fmail2.qdit> In-Reply-To: <1779078055.630771314@fmail2.qdit> From: Matthias van de Meent Date: Mon, 6 Jul 2026 17:44:50 +0200 X-Gm-Features: AVVi8Cczh2FNngIEyN4_wfHpR-2iZrMIrDWI4KajnhV5jy8P-Pn-S-GisU1xx3c Message-ID: Subject: Re: VACUUM FULL or CREATE INDEX fails with error: missing chunk number 0 for toast value XXX To: =?UTF-8?B?0KLQtdGB0YLQvtCy0LAg0JXQutCw0YLQtdGA0LjQvdCw?= Cc: pgsql-hackers@postgresql.org Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Tue, 19 May 2026 at 23:05, =D0=A2=D0=B5=D1=81=D1=82=D0=BE=D0=B2=D0=B0 = =D0=95=D0=BA=D0=B0=D1=82=D0=B5=D1=80=D0=B8=D0=BD=D0=B0 wrote: > > Bug ERROR: missing chunk number 0 for toast value. > The bug #18351 was previously reported in https://www.postgresql.org/mess= age-id/flat/18351-f6e06364b3a2e669%40postgresql.org but not resolved. > I have made reproducing easier, figured out the cause of the bug, and dev= eloped > a prototype patch, though it has known issues I'd like feedback on. [ summary of the problem; toast table cleanup racing with index creation & vacuum full that needs access to RECENTLY_DEAD tuples' toast data ] > Prototype patch > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > The core idea: when vacuuming a TOAST table, reuse the OldestXmin that wa= s > computed for the parent table, rather than computing a fresh one that > may have advanced past it. I think this is insufficient; heap on-access pruning and btree's aggressive index tuple removal (when the page would split) will still cause some cleanup of data that could still be considered RECENTLY_DEAD by a possible concurrent maintenance session (CREATE INDEX, REINDEX, VACUUM FULL, ...). I suspect the only possible approach here is to be extra careful when detoasting attributes of RECENTLY_DEAD tuples, and just skip RECENTLY_DEAD tuples if they are missing any parts of their externally toasted attributes. We *can* reduce the likelyhood of this issue by regularly updating the OldestXmin used for HeapTupleSatisfiesVacuum() with more recent GetOldestNonRemovableTransactionId(heapRelation) in e.g. heapam_index_build_range_scan, but I can guarantee that it won't be a universal fix for the issue: We still determine the liveness (well, scan inclusion) of the heap tuple ahead of reading the toast data, and in the time between those two page accesses there is more than enough time for a concurrent session to come in and prune the toast page that holds the equally RECENTLY_DEAD toast tuples, or remove the items from the btree with bottom-up index removal. So, missing toast data is (sadly) to be expected when working with RECENTLY_DEAD tuples. We'll "just" have to find a way to avoid completely erroring out in those contexts. > Alternative approach > =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D > An alternative would be to add a definitely_needed check alongside > OldestXmin in create index, so that a tuple classified as RECENTLY_DEAD > by OldestXmin would be reclassified as DEAD if definitely_needed says it'= s safe > to remove. However, this adds an extra visibility check during CREATE IND= EX, > which could cause a performance regression. OldestXmin is already populated by (what should be) the value of the relevant GlobalVisState.definitely_needed; it's just never updated during an index build. Adding additional checks won't help any more than just updating the OldestXmin horizon used. > I'd appreciate comments on whether the "cache parent OldestXmin for TOAST > vacuum" approach worth pursuing, despite the freezing complications? > Or is there a cleaner way? I don't think either approach is sufficient to fix the bug; see my inline comments about the issues. I think the simplest way to reduce the frequency of the INDEX issue is to regularly update OldestXmin, but to completely fix the bug we'll probably have to start materializing relevant toasted attributes more aggressively before passing the tuple to the IndexBuildCallback. Any TOAST-related visibility errors can then be ignored, rather than breaking the index build state due to unexpected errors when materializing the data. Kind regards, Matthias van de Meent Databricks (https://www.databricks.com)