Skip to content

Commit

Permalink
Remove the "snapshot too old" feature.
Browse files Browse the repository at this point in the history
Remove the old_snapshot_threshold setting and mechanism for producing
the error "snapshot too old", originally added by commit 848ef42.
Unfortunately it had a number of known problems in terms of correctness
and performance, mostly reported by Andres in the course of his work on
snapshot scalability.  We agreed to remove it, after a long period
without an active plan to fix it.

This is certainly a desirable feature, and someone might propose a new
or improved implementation in the future.

Reported-by: Andres Freund <andres@anarazel.de>
Discussion: https://postgr.es/m/CACG%3DezYV%2BEvO135fLRdVn-ZusfVsTY6cH1OZqWtezuEYH6ciQA%40mail.gmail.com
Discussion: https://postgr.es/m/20200401064008.qob7bfnnbu4w5cw4%40alap3.anarazel.de
Discussion: https://postgr.es/m/CA%2BTgmoY%3Daqf0zjTD%2B3dUWYkgMiNDegDLFjo%2B6ze%3DWtpik%2B3XqA%40mail.gmail.com
  • Loading branch information
macdice committed Sep 5, 2023
1 parent aa0d350 commit f691f5b
Show file tree
Hide file tree
Showing 50 changed files with 21 additions and 1,425 deletions.
1 change: 0 additions & 1 deletion contrib/Makefile
Expand Up @@ -29,7 +29,6 @@ SUBDIRS = \
lo \
ltree \
oid2name \
old_snapshot \
pageinspect \
passwordcheck \
pg_buffercache \
Expand Down
1 change: 0 additions & 1 deletion contrib/bloom/blscan.c
Expand Up @@ -132,7 +132,6 @@ blgetbitmap(IndexScanDesc scan, TIDBitmap *tbm)

LockBuffer(buffer, BUFFER_LOCK_SHARE);
page = BufferGetPage(buffer);
TestForOldSnapshot(scan->xs_snapshot, scan->indexRelation, page);

if (!PageIsNew(page) && !BloomPageIsDeleted(page))
{
Expand Down
1 change: 0 additions & 1 deletion contrib/meson.build
Expand Up @@ -37,7 +37,6 @@ subdir('lo')
subdir('ltree')
subdir('ltree_plpython')
subdir('oid2name')
subdir('old_snapshot')
subdir('pageinspect')
subdir('passwordcheck')
subdir('pg_buffercache')
Expand Down
21 changes: 0 additions & 21 deletions contrib/old_snapshot/Makefile

This file was deleted.

23 changes: 0 additions & 23 deletions contrib/old_snapshot/meson.build

This file was deleted.

14 changes: 0 additions & 14 deletions contrib/old_snapshot/old_snapshot--1.0.sql

This file was deleted.

5 changes: 0 additions & 5 deletions contrib/old_snapshot/old_snapshot.control

This file was deleted.

142 changes: 0 additions & 142 deletions contrib/old_snapshot/time_mapping.c

This file was deleted.

69 changes: 0 additions & 69 deletions doc/src/sgml/config.sgml
Expand Up @@ -2709,65 +2709,6 @@ include_dir 'conf.d'
</para>
</listitem>
</varlistentry>

<varlistentry id="guc-old-snapshot-threshold" xreflabel="old_snapshot_threshold">
<term><varname>old_snapshot_threshold</varname> (<type>integer</type>)
<indexterm>
<primary><varname>old_snapshot_threshold</varname> configuration parameter</primary>
</indexterm>
</term>
<listitem>
<para>
Sets the minimum amount of time that a query snapshot can be used
without risk of a <quote>snapshot too old</quote> error occurring
when using the snapshot. Data that has been dead for longer than
this threshold is allowed to be vacuumed away. This can help
prevent bloat in the face of snapshots which remain in use for a
long time. To prevent incorrect results due to cleanup of data which
would otherwise be visible to the snapshot, an error is generated
when the snapshot is older than this threshold and the snapshot is
used to read a page which has been modified since the snapshot was
built.
</para>

<para>
If this value is specified without units, it is taken as minutes.
A value of <literal>-1</literal> (the default) disables this feature,
effectively setting the snapshot age limit to infinity.
This parameter can only be set at server start.
</para>

<para>
Useful values for production work probably range from a small number
of hours to a few days. Small values (such as <literal>0</literal> or
<literal>1min</literal>) are only allowed because they may sometimes be
useful for testing. While a setting as high as <literal>60d</literal> is
allowed, please note that in many workloads extreme bloat or
transaction ID wraparound may occur in much shorter time frames.
</para>

<para>
When this feature is enabled, freed space at the end of a relation
cannot be released to the operating system, since that could remove
information needed to detect the <quote>snapshot too old</quote>
condition. All space allocated to a relation remains associated with
that relation for reuse only within that relation unless explicitly
freed (for example, with <command>VACUUM FULL</command>).
</para>

<para>
This setting does not attempt to guarantee that an error will be
generated under any particular circumstances. In fact, if the
correct results can be generated from (for example) a cursor which
has materialized a result set, no error will be generated even if the
underlying rows in the referenced table have been vacuumed away.
Some tables cannot safely be vacuumed early, and so will not be
affected by this setting, such as system catalogs. For such tables
this setting will neither reduce bloat nor create a possibility
of a <quote>snapshot too old</quote> error on scanning.
</para>
</listitem>
</varlistentry>
</variablelist>
</sect2>
</sect1>
Expand Down Expand Up @@ -4783,16 +4724,6 @@ ANY <replaceable class="parameter">num_sync</replaceable> ( <replaceable class="
until it eventually reaches the primary. Standbys make no other use
of feedback they receive other than to pass upstream.
</para>
<para>
This setting does not override the behavior of
<varname>old_snapshot_threshold</varname> on the primary; a snapshot on the
standby which exceeds the primary's age threshold can become invalid,
resulting in cancellation of transactions on the standby. This is
because <varname>old_snapshot_threshold</varname> is intended to provide an
absolute limit on the time which dead rows can contribute to bloat,
which would otherwise be violated because of the configuration of a
standby.
</para>
</listitem>
</varlistentry>

Expand Down
1 change: 0 additions & 1 deletion doc/src/sgml/contrib.sgml
Expand Up @@ -150,7 +150,6 @@ CREATE EXTENSION <replaceable>extension_name</replaceable>;
&isn;
&lo;
&ltree;
&oldsnapshot;
&pageinspect;
&passwordcheck;
&pgbuffercache;
Expand Down
1 change: 0 additions & 1 deletion doc/src/sgml/filelist.sgml
Expand Up @@ -138,7 +138,6 @@
<!ENTITY lo SYSTEM "lo.sgml">
<!ENTITY ltree SYSTEM "ltree.sgml">
<!ENTITY oid2name SYSTEM "oid2name.sgml">
<!ENTITY oldsnapshot SYSTEM "oldsnapshot.sgml">
<!ENTITY pageinspect SYSTEM "pageinspect.sgml">
<!ENTITY passwordcheck SYSTEM "passwordcheck.sgml">
<!ENTITY pgbuffercache SYSTEM "pgbuffercache.sgml">
Expand Down
33 changes: 0 additions & 33 deletions doc/src/sgml/oldsnapshot.sgml

This file was deleted.

7 changes: 0 additions & 7 deletions src/backend/access/brin/brin_revmap.c
Expand Up @@ -79,7 +79,6 @@ brinRevmapInitialize(Relation idxrel, BlockNumber *pagesPerRange,
meta = ReadBuffer(idxrel, BRIN_METAPAGE_BLKNO);
LockBuffer(meta, BUFFER_LOCK_SHARE);
page = BufferGetPage(meta);
TestForOldSnapshot(snapshot, idxrel, page);
metadata = (BrinMetaPageData *) PageGetContents(page);

revmap = palloc(sizeof(BrinRevmap));
Expand Down Expand Up @@ -277,7 +276,6 @@ brinGetTupleForHeapBlock(BrinRevmap *revmap, BlockNumber heapBlk,
}
LockBuffer(*buf, mode);
page = BufferGetPage(*buf);
TestForOldSnapshot(snapshot, idxRel, page);

/* If we land on a revmap page, start over */
if (BRIN_IS_REGULAR_PAGE(page))
Expand Down Expand Up @@ -372,11 +370,6 @@ brinRevmapDesummarizeRange(Relation idxrel, BlockNumber heapBlk)
LockBuffer(regBuf, BUFFER_LOCK_EXCLUSIVE);
regPg = BufferGetPage(regBuf);

/*
* We're only removing data, not reading it, so there's no need to
* TestForOldSnapshot here.
*/

/* if this is no longer a regular page, tell caller to start over */
if (!BRIN_IS_REGULAR_PAGE(regPg))
{
Expand Down

0 comments on commit f691f5b

Please sign in to comment.