Skip to content

Commit ef03ea0

Browse files
committed
Ignore temporary relations in RelidByRelfilenumber()
Temporary relations may share the same RelFileNumber with a permanent relation, or other temporary relations associated with other sessions. Being able to uniquely identify a temporary relation would require RelidByRelfilenumber() to know about the proc number of the temporary relation it wants to identify, something it is not designed for since its introduction in f01d1ae. There are currently three callers of RelidByRelfilenumber(): - autoprewarm. - Logical decoding, reorder buffer. - pg_filenode_relation(), that attempts to find a relation OID based on a tablespace OID and a RelFileNumber. This makes the situation problematic particularly for the first two cases, leading to the possibility of random ERRORs due to inconsistencies that temporary relations can create in the cache maintained by RelidByRelfilenumber(). The third case should be less of an issue, as I suspect that there are few direct callers of pg_filenode_relation(). The window where the ERRORs are happen is very narrow, requiring an OID wraparound to create a lookup conflict in RelidByRelfilenumber() with a temporary table reusing the same OID as another relation already cached. The problem is easier to reach in workloads with a high OID consumption rate, especially with a higher number of temporary relations created. We could get pg_filenode_relation() and RelidByRelfilenumber() to work with temporary relations if provided the means to identify them with an optional proc number given in input, but the years have also shown that we do not have a use case for it, yet. Note that this could not be backpatched if pg_filenode_relation() needs changes. It is simpler to ignore temporary relations. Reported-by: Shenhao Wang <wangsh.fnst@fujitsu.com> Author: Vignesh C <vignesh21@gmail.com> Reviewed-By: Ashutosh Bapat <ashutosh.bapat.oss@gmail.com> Reviewed-By: Robert Haas <robertmhaas@gmail.com> Reviewed-By: Kyotaro Horiguchi <horikyota.ntt@gmail.com> Reviewed-By: Takamichi Osumi <osumi.takamichi@fujitsu.com> Reviewed-By: Michael Paquier <michael@paquier.xyz> Reviewed-By: Masahiko Sawada <sawada.mshk@gmail.com> Reported-By: Shenhao Wang <wangsh.fnst@fujitsu.com> Discussion: https://postgr.es/m/bbaaf9f9-ebb2-645f-54bb-34d6efc7ac42@fujitsu.com Backpatch-through: 13
1 parent 47932f3 commit ef03ea0

File tree

7 files changed

+41
-4
lines changed

7 files changed

+41
-4
lines changed

doc/src/sgml/func/func-admin.sgml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1834,7 +1834,8 @@ postgres=# SELECT '0/0'::pg_lsn + pd.segment_number * ps.setting::int + :offset
18341834
<function>pg_relation_filepath</function>. For a relation in the
18351835
database's default tablespace, the tablespace can be specified as zero.
18361836
Returns <literal>NULL</literal> if no relation in the current database
1837-
is associated with the given values.
1837+
is associated with the given values, or if dealing with a temporary
1838+
relation.
18381839
</para></entry>
18391840
</row>
18401841
</tbody>

src/backend/utils/adt/dbsize.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -938,6 +938,9 @@ pg_relation_filenode(PG_FUNCTION_ARGS)
938938
*
939939
* We don't fail but return NULL if we cannot find a mapping.
940940
*
941+
* Temporary relations are not detected, returning NULL (see
942+
* RelidByRelfilenumber() for the reasons).
943+
*
941944
* InvalidOid can be passed instead of the current database's default
942945
* tablespace.
943946
*/

src/backend/utils/cache/relfilenumbermap.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,11 @@ InitializeRelfilenumberMap(void)
130130
* Map a relation's (tablespace, relfilenumber) to a relation's oid and cache
131131
* the result.
132132
*
133+
* A temporary relation may share its relfilenumber with a permanent relation
134+
* or temporary relations created in other backends. Being able to uniquely
135+
* identify a temporary relation would require a backend's proc number, which
136+
* we do not know about. Hence, this function ignores this case.
137+
*
133138
* Returns InvalidOid if no relation matching the criteria could be found.
134139
*/
135140
Oid
@@ -208,6 +213,9 @@ RelidByRelfilenumber(Oid reltablespace, RelFileNumber relfilenumber)
208213
{
209214
Form_pg_class classform = (Form_pg_class) GETSTRUCT(ntp);
210215

216+
if (classform->relpersistence == RELPERSISTENCE_TEMP)
217+
continue;
218+
211219
if (found)
212220
elog(ERROR,
213221
"unexpected duplicate for tablespace %u, relfilenumber %u",

src/test/regress/expected/alter_table.out

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3567,12 +3567,15 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F
35673567
-- filenode function call can return NULL for a relation dropped concurrently
35683568
-- with the call's surrounding query, so ignore a NULL mapped_oid for
35693569
-- relations that no longer exist after all calls finish.
3570+
-- Temporary relations are ignored, as not supported by pg_filenode_relation().
35703571
CREATE TEMP TABLE filenode_mapping AS
35713572
SELECT
35723573
oid, mapped_oid, reltablespace, relfilenode, relname
35733574
FROM pg_class,
35743575
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
3575-
WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
3576+
WHERE relkind IN ('r', 'i', 'S', 't', 'm')
3577+
AND relpersistence != 't'
3578+
AND mapped_oid IS DISTINCT FROM oid;
35763579
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
35773580
WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
35783581
oid | mapped_oid | reltablespace | relfilenode | relname

src/test/regress/expected/create_table.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,18 @@ ERROR: tables declared WITH OIDS are not supported
102102
-- but explicitly not adding oids is still supported
103103
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
104104
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
105+
-- temporary tables are ignored by pg_filenode_relation().
106+
CREATE TEMP TABLE relation_filenode_check(c1 int);
107+
SELECT relpersistence,
108+
pg_filenode_relation (reltablespace, pg_relation_filenode(oid))
109+
FROM pg_class
110+
WHERE relname = 'relation_filenode_check';
111+
relpersistence | pg_filenode_relation
112+
----------------+----------------------
113+
t |
114+
(1 row)
115+
116+
DROP TABLE relation_filenode_check;
105117
-- check restriction with default expressions
106118
-- invalid use of column reference in default expressions
107119
CREATE TABLE default_expr_column (id int DEFAULT (id));

src/test/regress/sql/alter_table.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2202,13 +2202,15 @@ SELECT conname as constraint, obj_description(oid, 'pg_constraint') as comment F
22022202
-- filenode function call can return NULL for a relation dropped concurrently
22032203
-- with the call's surrounding query, so ignore a NULL mapped_oid for
22042204
-- relations that no longer exist after all calls finish.
2205+
-- Temporary relations are ignored, as not supported by pg_filenode_relation().
22052206
CREATE TEMP TABLE filenode_mapping AS
22062207
SELECT
22072208
oid, mapped_oid, reltablespace, relfilenode, relname
22082209
FROM pg_class,
22092210
pg_filenode_relation(reltablespace, pg_relation_filenode(oid)) AS mapped_oid
2210-
WHERE relkind IN ('r', 'i', 'S', 't', 'm') AND mapped_oid IS DISTINCT FROM oid;
2211-
2211+
WHERE relkind IN ('r', 'i', 'S', 't', 'm')
2212+
AND relpersistence != 't'
2213+
AND mapped_oid IS DISTINCT FROM oid;
22122214
SELECT m.* FROM filenode_mapping m LEFT JOIN pg_class c ON c.oid = m.oid
22132215
WHERE c.oid IS NOT NULL OR m.mapped_oid IS NOT NULL;
22142216

src/test/regress/sql/create_table.sql

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,14 @@ CREATE TABLE withoid() WITH (oids = true);
6868
CREATE TEMP TABLE withoutoid() WITHOUT OIDS; DROP TABLE withoutoid;
6969
CREATE TEMP TABLE withoutoid() WITH (oids = false); DROP TABLE withoutoid;
7070

71+
-- temporary tables are ignored by pg_filenode_relation().
72+
CREATE TEMP TABLE relation_filenode_check(c1 int);
73+
SELECT relpersistence,
74+
pg_filenode_relation (reltablespace, pg_relation_filenode(oid))
75+
FROM pg_class
76+
WHERE relname = 'relation_filenode_check';
77+
DROP TABLE relation_filenode_check;
78+
7179
-- check restriction with default expressions
7280
-- invalid use of column reference in default expressions
7381
CREATE TABLE default_expr_column (id int DEFAULT (id));

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy