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 1rh8m2-009ogy-GY for pgsql-hackers@arkaria.postgresql.org; Mon, 04 Mar 2024 13:54:35 +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 1rh8m0-008IDs-Ko for pgsql-hackers@arkaria.postgresql.org; Mon, 04 Mar 2024 13:54:33 +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.94.2) (envelope-from ) id 1rh8m0-008IDj-8C for pgsql-hackers@lists.postgresql.org; Mon, 04 Mar 2024 13:54:32 +0000 Received: from mail-wr1-x431.google.com ([2a00:1450:4864:20::431]) by magus.postgresql.org with esmtps (TLS1.3) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.94.2) (envelope-from ) id 1rh8lx-002jFg-8P for pgsql-hackers@lists.postgresql.org; Mon, 04 Mar 2024 13:54:31 +0000 Received: by mail-wr1-x431.google.com with SMTP id ffacd0b85a97d-33e122c8598so2658814f8f.1 for ; Mon, 04 Mar 2024 05:54:29 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=aiven.io; s=google; t=1709560467; x=1710165267; darn=lists.postgresql.org; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:from:to:cc:subject:date:message-id:reply-to; bh=VXuSI5L9UmbWlbJbMV7mOxd/+Id4ZJ6dR3v+TgNqGIg=; b=aMQ1yrVdyTSc6LBCA40k7Lf9PpFivOHCLbuBjNK4BeU1WsHx9Klsq3Yiu1ev8NwqHp P/qrFXvqOTHcpzBvf0zDondTTN1L2iK8T8/VD9CMWMT2VDyYVEe3fX6f32UNvIGrHG5Y hke3o8ei5bopOBQjkj7P7LO6jO8FR6uE3HkxY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1709560467; x=1710165267; h=content-transfer-encoding:mime-version:message-id:date:subject:to :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=VXuSI5L9UmbWlbJbMV7mOxd/+Id4ZJ6dR3v+TgNqGIg=; b=BTdMb49RTHUuts9LiuqVLKHu0QMOaJPMpMpmnxFhjwpeLacHVZfF5DbrMButCycSX8 j1TQxhAe46OOiSoaTQgSUDGX83dgUInXnV7KkkTf5AgtLF8dGr2e5EG7q6IgO9nyiMYA okSjjeK4aXoxxzJ6tjjTypImrtEawW25ZYv+nw3IP+K1uE30a4uThL691qSz1+PqO/WJ cirtsHJtIIYjUB126zvyTYnWBhbHU2MH6vw+JgKVJu20vMfrFDWsJdHig0omblvrxyf0 sQPYGj+JM29Pm2Y39Gg2xkKXTvKTYD1eynFKwXDZprU1LjA7fMz8xi5O0oJS2YO0KoWq 2S+w== X-Gm-Message-State: AOJu0YxXCubHjkus5aRJbqpRuFdoO8c90OwHS/M2DgVhlJI3xvgw2Mca 2E8xY8aRYm2PftT7dVjZcNQQZFNgrQsgld/IW5zYUNQBq/exV/mQQtYdpfcxwNyOrBGEERqMqOp c/aO6tOTL3zaOGr9tzdT2XimOebtlIxXW424aPp23S9L1lwiMxavfVuo4DJQAA7GmMvzCpVuNBP rcQ9nBAN1UbMrLakse6RBBYGfynA4ExNysPunAm3s46JfW6uMDOe1Feki6 X-Google-Smtp-Source: AGHT+IHEqunt0Id0iHiMJ8c0fymBcp6q7euhUsTMPO7yOhbVDEbr86Me7LiQCE1060yvnC9ssSUNyA== X-Received: by 2002:adf:f987:0:b0:33e:4212:42b3 with SMTP id f7-20020adff987000000b0033e421242b3mr1276127wrr.65.1709560466724; Mon, 04 Mar 2024 05:54:26 -0800 (PST) Received: from aivenlaptop.localnet ([45.13.105.93]) by smtp.gmail.com with ESMTPSA id h12-20020adf9ccc000000b0033e03a6b1ecsm12281869wre.18.2024.03.04.05.54.26 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 04 Mar 2024 05:54:26 -0800 (PST) From: Ronan Dunklau To: pgsql-hackers@lists.postgresql.org Subject: Provide a pg_truncate_freespacemap function Date: Mon, 04 Mar 2024 14:54:25 +0100 Message-ID: <5446938.Sb9uPGUboI@aivenlaptop> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="nextPart1969751.yKVeVyVuyW" Content-Transfer-Encoding: 7Bit List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Archived-At: Precedence: bulk This is a multi-part message in MIME format. --nextPart1969751.yKVeVyVuyW Content-Transfer-Encoding: 7Bit Content-Type: text/plain; charset="us-ascii" Hello, As we are currently experiencing a FSM corruption issue [1], we need to rebuild FSM when we detect it. I noticed we have something to truncate a visibility map, but nothing for the freespace map, so I propose the attached (liberally copied from the VM counterpart) to allow to truncate a FSM without incurring downtime, as currently our only options are to either VACUUM FULL the table or stop the cluster and remove the FSM manually. Does that seem correct ? [1] https://www.postgresql.org/message-id/flat/ 1925490.taCxCBeP46%40aivenlaptop#7ace95c95cab17b6d92607e5362984ac -- Ronan Dunklau --nextPart1969751.yKVeVyVuyW Content-Disposition: attachment; filename="0001-Provide-a-pg_truncate_freespacemap-function.patch" Content-Transfer-Encoding: 7Bit Content-Type: text/x-patch; charset="x-UTF_8J"; name="0001-Provide-a-pg_truncate_freespacemap-function.patch" From b3e28e4542311094ee7177b39cc9cdf3672d1b55 Mon Sep 17 00:00:00 2001 From: Ronan Dunklau Date: Fri, 1 Mar 2024 08:57:49 +0100 Subject: [PATCH] Provide a pg_truncate_freespacemap function. Similar to the pg_truncate_visibilitymap function, this one allows to avoid downtime to fix an FSM in the case a corruption event happens --- contrib/pg_freespacemap/Makefile | 5 +- .../pg_freespacemap--1.2--1.3.sql | 13 +++++ contrib/pg_freespacemap/pg_freespacemap.c | 58 +++++++++++++++++++ .../pg_freespacemap/pg_freespacemap.control | 2 +- 4 files changed, 75 insertions(+), 3 deletions(-) create mode 100644 contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql diff --git a/contrib/pg_freespacemap/Makefile b/contrib/pg_freespacemap/Makefile index b48e4b255bc..0f4b52f5812 100644 --- a/contrib/pg_freespacemap/Makefile +++ b/contrib/pg_freespacemap/Makefile @@ -6,8 +6,9 @@ OBJS = \ pg_freespacemap.o EXTENSION = pg_freespacemap -DATA = pg_freespacemap--1.1.sql pg_freespacemap--1.1--1.2.sql \ - pg_freespacemap--1.0--1.1.sql +DATA = pg_freespacemap--1.1.sql pg_freespacemap--1.2--1.3.sql \ + pg_freespacemap--1.1--1.2.sql \ + pg_freespacemap--1.0--1.1.sql PGFILEDESC = "pg_freespacemap - monitoring of free space map" REGRESS_OPTS = --temp-config $(top_srcdir)/contrib/pg_freespacemap/pg_freespacemap.conf diff --git a/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql b/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql new file mode 100644 index 00000000000..1f25877a175 --- /dev/null +++ b/contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql @@ -0,0 +1,13 @@ +/* contrib/pg_freespacemap/pg_freespacemap--1.2--1.3.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION pg_freespacemap UPDATE TO '1.3'" to load this file. \quit + +CREATE FUNCTION pg_truncate_freespace_map(regclass) +RETURNS void +AS 'MODULE_PATHNAME', 'pg_truncate_freespace_map' +LANGUAGE C STRICT +PARALLEL UNSAFE; + + + diff --git a/contrib/pg_freespacemap/pg_freespacemap.c b/contrib/pg_freespacemap/pg_freespacemap.c index b82cab2d97e..17f6a631ad8 100644 --- a/contrib/pg_freespacemap/pg_freespacemap.c +++ b/contrib/pg_freespacemap/pg_freespacemap.c @@ -9,8 +9,12 @@ #include "postgres.h" #include "access/relation.h" +#include "access/xloginsert.h" +#include "catalog/storage_xlog.h" #include "funcapi.h" #include "storage/freespace.h" +#include "storage/smgr.h" +#include "utils/rel.h" PG_MODULE_MAGIC; @@ -20,6 +24,9 @@ PG_MODULE_MAGIC; */ PG_FUNCTION_INFO_V1(pg_freespace); +/* Truncate the free space map, in case of corruption */ +PG_FUNCTION_INFO_V1(pg_truncate_freespace_map); + Datum pg_freespace(PG_FUNCTION_ARGS) { @@ -40,3 +47,54 @@ pg_freespace(PG_FUNCTION_ARGS) relation_close(rel, AccessShareLock); PG_RETURN_INT16(freespace); } + + +Datum +pg_truncate_freespace_map(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + Relation rel; + ForkNumber fork; + BlockNumber block; + + rel = relation_open(relid, AccessExclusiveLock); + + /* Only some relkinds have a freespacemap */ + if (!RELKIND_HAS_TABLE_AM(rel->rd_rel->relkind)) + ereport(ERROR, + (errcode(ERRCODE_WRONG_OBJECT_TYPE), + errmsg("relation \"%s\" is of wrong relation kind", + RelationGetRelationName(rel)), + errdetail_relkind_not_supported(rel->rd_rel->relkind))); + + + /* Forcibly reset cached file size */ + RelationGetSmgr(rel)->smgr_cached_nblocks[FSM_FORKNUM] = InvalidBlockNumber; + + /* Just pretend we're going to wipeout the whole rel */ + block = FreeSpaceMapPrepareTruncateRel(rel, 0); + + if (BlockNumberIsValid(block)) + { + fork = FSM_FORKNUM; + smgrtruncate(RelationGetSmgr(rel), &fork, 1, &block); + } + + if (RelationNeedsWAL(rel)) + { + xl_smgr_truncate xlrec; + + xlrec.blkno = 0; + xlrec.rlocator = rel->rd_locator; + xlrec.flags = SMGR_TRUNCATE_FSM; + + XLogBeginInsert(); + XLogRegisterData((char *) &xlrec, sizeof(xlrec)); + + XLogInsert(RM_SMGR_ID, XLOG_SMGR_TRUNCATE | XLR_SPECIAL_REL_UPDATE); + } + + relation_close(rel, AccessExclusiveLock); + + PG_RETURN_VOID(); +} diff --git a/contrib/pg_freespacemap/pg_freespacemap.control b/contrib/pg_freespacemap/pg_freespacemap.control index ac8fc5050a9..1992320691b 100644 --- a/contrib/pg_freespacemap/pg_freespacemap.control +++ b/contrib/pg_freespacemap/pg_freespacemap.control @@ -1,5 +1,5 @@ # pg_freespacemap extension comment = 'examine the free space map (FSM)' -default_version = '1.2' +default_version = '1.3' module_pathname = '$libdir/pg_freespacemap' relocatable = true -- 2.43.2 --nextPart1969751.yKVeVyVuyW--