pg.ddx.io  pgsql-bugs@postgresql.org mailing list archive  
help / color / mirror / Atom feed
From: Ronan Dunklau <ronan.dunklau@aiven.io>
To: Noah Misch <noah@leadboat.com>
To: Michael Paquier <michael@paquier.xyz>
Cc: pgsql-bugs <pgsql-bugs@lists.postgresql.org>
Subject: Re: FSM Corruption (was: Could not read block at end of the relation)
Date: Wed, 06 Mar 2024 10:31:17 +0100
Message-ID: <1958756.PYKUYFuaPT@aivenlaptop> (raw)
In-Reply-To: <3609363.R56niFO833@aivenlaptop>
References: <VtPLBUerbMM8BSDLQwIMV9Co_38iHS1TXE4V09x2ZVFhPkZMNE8LwgPSIzB8PHkVFXykGx04QNAzZVjJFAnU1w==@protonmail.internalid>
	<TlHm41R71dghOEOJPrzhuxhrDI1R50MRIXHcVzU9BuJpSPKXypIYH9m5BrdxSGM_tE3DlXKFXLesUnd7vR1pxg==@protonmail.internalid>
	<3609363.R56niFO833@aivenlaptop>

Le mardi 5 mars 2024, 00:05:03 CET Noah Misch a écrit :
> I would guess this one is more risky from a performance perspective, since
> we'd be adding to a hotter path under RelationGetBufferForTuple().  Still,
> it's likely fine.

I ended up implementing this in the attached patch. The idea is that we detect 
if the FSM returns a page past the end of the relation, and ignore it.
In that case we will fallback through the extension mechanism.

For the corrupted-FSM case it is not great performance wise, as we will extend 
the relation in small steps every time we find a non existing block in the FSM, 
until the actual relation size matches what is recorded in the FSM. But since 
those seldom happen, I figured it was better to keep the code really simple for 
a bugfix.

I wanted to test the impact in terms of performance, and I thought about the 
worst possible case for this.

Then, run a pgbench doing insertions in the table. With the attached patch the 
worst case I could come up with is: 
  - remember which page we last inserted into
  - notice we don't have enough space
  - ask the FSM for a block
  - now have to compare that to the actual relation size

So I came up with the following initialization steps:

 - create a table with vacuum_truncate = off, with a tuple size big enough that 
it's impossible to fit two tuples on the same page
 - insert lots of tuple in it until it reaches a decent size
 - delete them all
 - vacuum
 - all of this fitting in shared_buffers

As in:

CREATE TABLE test_perf (c1 char(5000));
ALTER TABLE test_perf ALTER c1 SET STORAGE PLAIN;
ALTER TABLE test_perf SET (VACUUM_TRUNCATE = off);
INSERT INTO test_perf (c1) SELECT 'c' FROM generate_series(1, 1000000);
DELETE FROM test_perf;
VACUUM test_perf;

Then I ran pgbench with a single client, with a script only inserting the same 
value over and over again, for 1000000 transactions (initial table size).

I noticed no difference running with or without the patch, but maybe someone 
else can try to run that or find another adversarial case ? 

Best regards,

--
Ronan Dunklau

Attachments:

  0001-Detect-invalid-FSM-when-finding-a-block.patch (text/x-patch, 0B) download

view thread (32+ messages)  latest in thread

Message-ID: <1958756.PYKUYFuaPT@aivenlaptop>
Permalink:  ../1958756.PYKUYFuaPT@aivenlaptop/
Also on:    postgresql.org/message-id/1958756.PYKUYFuaPT@aivenlaptop

 ·  · 

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: pgsql-bugs@postgresql.org
  Cc: ronan.dunklau@aiven.io, noah@leadboat.com, michael@paquier.xyz, pgsql-bugs@lists.postgresql.org
  Subject: Re: FSM Corruption (was: Could not read block at end of the relation)
  In-Reply-To: <1958756.PYKUYFuaPT@aivenlaptop>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox