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.94.2) (envelope-from ) id 1rhDas-00AFzU-Ny for pgsql-bugs@arkaria.postgresql.org; Mon, 04 Mar 2024 19:03:23 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.94.2) (envelope-from ) id 1rhDap-00AAbe-GY for pgsql-bugs@arkaria.postgresql.org; Mon, 04 Mar 2024 19:03:19 +0000 Received: from makus.postgresql.org ([2001:4800:3e1:1::229]) by malur.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 (Exim 4.94.2) (envelope-from ) id 1rhDap-00AAbW-8a for pgsql-bugs@lists.postgresql.org; Mon, 04 Mar 2024 19:03:19 +0000 Received: from mail-il1-x133.google.com ([2607:f8b0:4864:20::133]) by makus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rhDal-002qGp-Po for pgsql-bugs@lists.postgresql.org; Mon, 04 Mar 2024 19:03:18 +0000 Received: by mail-il1-x133.google.com with SMTP id e9e14a558f8ab-36524116e30so18441505ab.0 for ; Mon, 04 Mar 2024 11:03:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=leadboat.com; s=google; t=1709578996; x=1710183796; darn=lists.postgresql.org; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:from:to:cc:subject:date:message-id:reply-to; bh=YUGf/jev5hFrZ8G+c+lOuBycKJ5kNU5J3BcLMyzm+6A=; b=HMDnJsrpOJ5I70R1k9rfyToEsd68FtBQY27z9Cdz7SduWGAVBzzHEOtC+zsoJ+XS6S DRObJ3qQzZXBnXPoxnHM8Y/VUjWv8T2WZw+UcM8hwTXqUSvca4JuK8XocE+G3G19Dxif zmFYyL5nEj5hYf52Zf/LjpwexEjs2aamROF6k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709578996; x=1710183796; h=user-agent:in-reply-to:content-transfer-encoding :content-disposition:mime-version:references:message-id:subject:cc :to:from:date:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=YUGf/jev5hFrZ8G+c+lOuBycKJ5kNU5J3BcLMyzm+6A=; b=P0NcSVQH6yVBnEkmqwUuodzShzhk09HQ6/vrw9eZSYAScxo0fuPD1hysAryPIdic20 ip4vEKE+r3bjK/OthtnYmIdjH3Ut4Lnnl6Z86/8/QQQyTqDtk23gnkYvhm9A7N8AzbRP aEOUHKbzkoo5Njwqkkwf6Sp6og2Ds3bj7e+nLkhPirPf3v8zevt1nvGJEC6t53C3us82 3VDIkS1jQotfdIBRj94D+GzXG6ZlHNXw5Ivka1rtpjDyhY5IafALQRV+KB9P0PxgDQBD /9HVy31hes8TG9w8hkBali9G7jTcnrd2z3rH+gseBeDw4ojborjSyhwdliVvvTA3O8V9 jIJg== X-Gm-Message-State: AOJu0Yx3iuqhPUheN0DQrL3efJR4vwvUtuhxS6H2/beIVHujLCAKCNOx CSdW3sT5y8d72Q1f6jXqwVxsbBXaPDZd1zYxsQaSQBp7aQB7US+VpboOhS0BFl5O7j8lfjZft58 = X-Google-Smtp-Source: AGHT+IF9SWlq7QERGnK1UBxdX99nfqjt4FLk+Ga+wT4FP2pxynUKwYFm4pBdh/pWWJMLt//Z1Hfs3Q== X-Received: by 2002:a05:6e02:1807:b0:365:69a:86b2 with SMTP id a7-20020a056e02180700b00365069a86b2mr14951276ilv.17.1709578995815; Mon, 04 Mar 2024 11:03:15 -0800 (PST) Received: from google.com ([2600:1702:a20:5750::48]) by smtp.gmail.com with ESMTPSA id c14-20020a25a28e000000b00dcdb6934617sm2197710ybi.62.2024.03.04.11.03.14 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 04 Mar 2024 11:03:15 -0800 (PST) Date: Mon, 4 Mar 2024 11:03:12 -0800 From: Noah Misch To: Ronan Dunklau Cc: pgsql-bugs Subject: Re: FSM Corruption (was: Could not read block at end of the relation) Message-ID: <20240304190312.b6.nmisch@google.com> References: <1958255.PYKUYFuaPT@aivenlaptop> <20240303234715.4d@rfd.leadboat.com> <1925490.taCxCBeP46@aivenlaptop> MIME-Version: 1.0 Content-Type: text/plain; charset=iso-8859-1 Content-Disposition: inline Content-Transfer-Encoding: 8bit In-Reply-To: <1925490.taCxCBeP46@aivenlaptop> User-Agent: Mutt/2.2.12 (2023-09-09) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk On Mon, Mar 04, 2024 at 02:10:39PM +0100, Ronan Dunklau wrote: > Le lundi 4 mars 2024, 00:47:15 CET Noah Misch a écrit : > > On Tue, Feb 27, 2024 at 11:34:14AM +0100, Ronan Dunklau wrote: > > > - happens during heavy system load > > > - lots of concurrent writes happening on a table > > > - often (but haven't been able to confirm it is necessary), a vacuum is > > > running on the table at the same time the error is triggered > Looking at when the corruption was WAL-logged, this particular case is quite > easy to trace. We have a few MULTI-INSERTS+INIT intiially loading the table > (probably a pg_restore), then, 2GB of WAL later, what looks like a VACUUM > running on the table: a succession of FPI_FOR_HINT, FREEZE_PAGE, VISIBLE xlog > records for each of the relation main fork, followed by a lonely FPI for the > leaf page of it's FSM: You're using data_checksums, right? Thanks for the wal dump excerpts; I agree with this summary thereof. > There are no traces of relation truncation happening in the WAL. That is notable. > This case only shows a single invalid entry in the FSM, but I've noticed as > much as 62 blocks present in the FSM while they do not exist on disk, all > tagged with MaxFSMRequestSize so I suppose something is wrong with the bulk > extension mechanism. Is this happening after an OS crash, a replica promote, or a PITR restore? If so, I think I see the problem. We have an undocumented rule that FSM shall not contain references to pages past the end of the relation. To facilitate that, relation truncation WAL-logs FSM truncate. However, there's no similar protection for relation extension, which is not WAL-logged. We break the rule whenever we write FSM for block X before some WAL record initializes block X. data_checksums makes the trouble easier to hit, since it creates FPI_FOR_HINT records for FSM changes. A replica promote or PITR ending just after the FSM FPI_FOR_HINT would yield this broken state. While v16 RelationAddBlocks() made this easier to hit, I suspect it's reproducible in all supported branches. For example, lazy_scan_new_or_empty() and multiple index AMs break the rule via RecordPageWithFreeSpace() on a PageIsNew() page. I think the fix is one of: - Revoke the undocumented rule. Make FSM consumers resilient to the FSM returning a now-too-large block number. - Enforce a new "main-fork WAL before FSM" rule for logged rels. For example, in each PageIsNew() case, either don't update FSM or WAL-log an init (like lazy_scan_new_or_empty() does when PageIsEmpty()).