Hi,

While testing concurrent operations involving pg_dump and ALTER
SEQUENCE, I found a race that can cause pg_dump to fail while reading
sequence data. pg_dump gathers each sequence's current last_value and
is_called by calling pg_get_sequence_data(), which opens the sequence
relation using AccessShareLock. However, AccessShareLock does not
conflict with the ShareRowExclusiveLock acquired by ALTER SEQUENCE. If
a definition-changing ALTER SEQUENCE command (for example, ALTER
SEQUENCE ... MINVALUE) commits after pg_get_sequence_data() has opened
the sequence relation but before it reads the on-disk sequence tuple,
the ALTER rewrites the sequence into a new relfilenode. As a result,
pg_get_sequence_data() which is trying to read from an old relfilenode
leading to an error such as:
could not read blocks 0..0 in file "base/.../...": read only 0 of 8192 bytes

I have attached patch
v1-0001-Add-a-TAP-test-to-reproduce-pg_dump-sequence-read.patch which
adds a TAP test that reproduces this race reliably. I'm attaching it
in case anyone wants to reproduce the problem locally, although I
don't think this test needs to be committed.

I think we should instead acquire a RowExclusiveLock rather than an
AccessShareLock in pg_get_sequence_data(), so that a concurrent ALTER
SEQUENCE waits until pg_get_sequence_data() has finished reading the
sequence. Attached
v1-0001-Prevent-concurrent-ALTER-SEQUENCE-from-racing-wit.patch which
has the changes for the same.

This appears to be an old issue from commit
7a485bd641b7bbf072146b97f70f9eb2c89f606a, where pg_get_sequence_data()
uses AccessShareLock. I was able to reproduce it on PostgreSQL 18 as
well.

Regards,
Vignesh

Attachment: v1-0001-Add-a-TAP-test-to-reproduce-pg_dump-sequence-read.patch
Description: Binary data

Attachment: v1-0001-Prevent-concurrent-ALTER-SEQUENCE-from-racing-wit.patch
Description: Binary data

Reply via email to