Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit6919b7e

Browse files
committed
Fix failure to ignore leftover temp tables after a server crash.
During crash recovery, we remove disk files belonging to temporary tables,but the system catalog entries for such tables are intentionally notcleaned up right away. Instead, the first backend that uses a temp schemais expected to clean out any leftover objects therein. This approachrequires that we be careful to ignore leftover temp tables (since anyactual access attempt would fail), *even if their BackendId matches oursession*, if we have not yet established use of the session's correspondingtemp schema. That worked fine in the past, but was broken by commitdebcec7 which incorrectly removed therd_islocaltemp relcache flag. Put it back, and undo various changesthat substituted tests like "rel->rd_backend == MyBackendId" for useof a state-aware flag. Per trouble report from Heikki Linnakangas.Back-patch to 9.1 where the erroneous change was made. In the backbranches, be careful to add rd_islocaltemp in a spot in the struct thatwas alignment padding before, so as not to break existing add-on code.
1 parentc299477 commit6919b7e

File tree

7 files changed

+64
-24
lines changed

7 files changed

+64
-24
lines changed

‎src/backend/catalog/toasting.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid, Datum reloptio
196196
* Toast tables for regular relations go in pg_toast; those for temp
197197
* relations go into the per-backend temp-toast-table namespace.
198198
*/
199-
if (RelationUsesTempNamespace(rel))
199+
if (isTempOrToastNamespace(rel->rd_rel->relnamespace))
200200
namespaceid=GetTempToastNamespace();
201201
else
202202
namespaceid=PG_TOAST_NAMESPACE;

‎src/backend/commands/copy.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ DoCopy(const CopyStmt *stmt, const char *queryString)
806806
Assert(rel);
807807

808808
/* check read-only transaction */
809-
if (XactReadOnly&&rel->rd_backend!=MyBackendId)
809+
if (XactReadOnly&&!rel->rd_islocaltemp)
810810
PreventCommandIfReadOnly("COPY FROM");
811811

812812
cstate=BeginCopyFrom(rel,stmt->filename,

‎src/backend/commands/sequence.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -553,7 +553,7 @@ nextval_internal(Oid relid)
553553
RelationGetRelationName(seqrel))));
554554

555555
/* read-only transactions may only modify temp sequences */
556-
if (seqrel->rd_backend!=MyBackendId)
556+
if (!seqrel->rd_islocaltemp)
557557
PreventCommandIfReadOnly("nextval()");
558558

559559
if (elm->last!=elm->cached)/* some numbers were cached */
@@ -846,7 +846,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
846846
RelationGetRelationName(seqrel))));
847847

848848
/* read-only transactions may only modify temp sequences */
849-
if (seqrel->rd_backend!=MyBackendId)
849+
if (!seqrel->rd_islocaltemp)
850850
PreventCommandIfReadOnly("setval()");
851851

852852
/* lock page' buffer and read tuple */

‎src/backend/commands/tablecmds.c

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1451,13 +1451,20 @@ MergeAttributes(List *schema, List *supers, char relpersistence,
14511451
errmsg("inherited relation \"%s\" is not a table",
14521452
parent->relname)));
14531453
/* Permanent rels cannot inherit from temporary ones */
1454-
if (relpersistence!=RELPERSISTENCE_TEMP
1455-
&&RelationUsesTempNamespace(relation))
1454+
if (relpersistence!=RELPERSISTENCE_TEMP&&
1455+
relation->rd_rel->relpersistence==RELPERSISTENCE_TEMP)
14561456
ereport(ERROR,
14571457
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
14581458
errmsg("cannot inherit from temporary relation \"%s\"",
14591459
parent->relname)));
14601460

1461+
/* If existing rel is temp, it must belong to this session */
1462+
if (relation->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
1463+
!relation->rd_islocaltemp)
1464+
ereport(ERROR,
1465+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
1466+
errmsg("cannot inherit from temporary relation of another session")));
1467+
14611468
/*
14621469
* We should have an UNDER permission flag for this, but for now,
14631470
* demand that creator of a child table own the parent.
@@ -5768,6 +5775,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
57685775
ereport(ERROR,
57695776
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
57705777
errmsg("constraints on temporary tables may reference only temporary tables")));
5778+
if (!pkrel->rd_islocaltemp|| !rel->rd_islocaltemp)
5779+
ereport(ERROR,
5780+
(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
5781+
errmsg("constraints on temporary tables must involve temporary tables of this session")));
57715782
break;
57725783
}
57735784

@@ -8884,13 +8895,27 @@ ATExecAddInherit(Relation child_rel, RangeVar *parent, LOCKMODE lockmode)
88848895
ATSimplePermissions(parent_rel,ATT_TABLE);
88858896

88868897
/* Permanent rels cannot inherit from temporary ones */
8887-
if (RelationUsesTempNamespace(parent_rel)
8888-
&& !RelationUsesTempNamespace(child_rel))
8898+
if (parent_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8899+
child_rel->rd_rel->relpersistence!=RELPERSISTENCE_TEMP)
88898900
ereport(ERROR,
88908901
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
88918902
errmsg("cannot inherit from temporary relation \"%s\"",
88928903
RelationGetRelationName(parent_rel))));
88938904

8905+
/* If parent rel is temp, it must belong to this session */
8906+
if (parent_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8907+
!parent_rel->rd_islocaltemp)
8908+
ereport(ERROR,
8909+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
8910+
errmsg("cannot inherit from temporary relation of another session")));
8911+
8912+
/* Ditto for the child */
8913+
if (child_rel->rd_rel->relpersistence==RELPERSISTENCE_TEMP&&
8914+
!child_rel->rd_islocaltemp)
8915+
ereport(ERROR,
8916+
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
8917+
errmsg("cannot inherit to temporary relation of another session")));
8918+
88948919
/*
88958920
* Check for duplicates in the list of parents, and determine the highest
88968921
* inhseqno already present; we'll use the next one for the new parent.

‎src/backend/utils/adt/dbsize.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ pg_tablespace_size_name(PG_FUNCTION_ARGS)
260260

261261
/*
262262
* calculate size of (one fork of) a relation
263+
*
264+
* Note: we can safely apply this to temp tables of other sessions, so there
265+
* is no check here or at the call sites for that.
263266
*/
264267
staticint64
265268
calculate_relation_size(RelFileNode*rfn,BackendIdbackend,ForkNumberforknum)
@@ -314,7 +317,7 @@ pg_relation_size(PG_FUNCTION_ARGS)
314317
* that makes queries like "SELECT pg_relation_size(oid) FROM pg_class"
315318
* less robust, because while we scan pg_class with an MVCC snapshot,
316319
* someone else might drop the table. It's better to return NULL for
317-
*alread-dropped tables than throw an error and abort the whole query.
320+
*already-dropped tables than throw an error and abort the whole query.
318321
*/
319322
if (rel==NULL)
320323
PG_RETURN_NULL();

‎src/backend/utils/cache/relcache.c

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -853,20 +853,33 @@ RelationBuildDesc(Oid targetRelId, bool insertIt)
853853
caseRELPERSISTENCE_UNLOGGED:
854854
caseRELPERSISTENCE_PERMANENT:
855855
relation->rd_backend=InvalidBackendId;
856+
relation->rd_islocaltemp= false;
856857
break;
857858
caseRELPERSISTENCE_TEMP:
858859
if (isTempOrToastNamespace(relation->rd_rel->relnamespace))
860+
{
859861
relation->rd_backend=MyBackendId;
862+
relation->rd_islocaltemp= true;
863+
}
860864
else
861865
{
862866
/*
863-
* If it's a local temp table, but not one of ours, we have to
864-
* use the slow, grotty method to figure out the owning
865-
* backend.
867+
* If it's a temp table, but not one of ours, we have to use
868+
* the slow, grotty method to figure out the owning backend.
869+
*
870+
* Note: it's possible that rd_backend gets set to MyBackendId
871+
* here, in case we are looking at a pg_class entry left over
872+
* from a crashed backend that coincidentally had the same
873+
* BackendId we're using. We should *not* consider such a
874+
* table to be "ours"; this is why we need the separate
875+
* rd_islocaltemp flag. The pg_class entry will get flushed
876+
* if/when we clean out the corresponding temp table namespace
877+
* in preparation for using it.
866878
*/
867879
relation->rd_backend=
868880
GetTempNamespaceBackendId(relation->rd_rel->relnamespace);
869881
Assert(relation->rd_backend!=InvalidBackendId);
882+
relation->rd_islocaltemp= false;
870883
}
871884
break;
872885
default:
@@ -1387,6 +1400,7 @@ formrdesc(const char *relationName, Oid relationReltype,
13871400
relation->rd_createSubid=InvalidSubTransactionId;
13881401
relation->rd_newRelfilenodeSubid=InvalidSubTransactionId;
13891402
relation->rd_backend=InvalidBackendId;
1403+
relation->rd_islocaltemp= false;
13901404

13911405
/*
13921406
* initialize relation tuple form
@@ -2538,16 +2552,19 @@ RelationBuildLocalRelation(const char *relname,
25382552
/* needed when bootstrapping: */
25392553
rel->rd_rel->relowner=BOOTSTRAP_SUPERUSERID;
25402554

2541-
/* set up persistence; rd_backend is a function of persistence type */
2555+
/* set up persistence and relcache fields dependent on it */
25422556
rel->rd_rel->relpersistence=relpersistence;
25432557
switch (relpersistence)
25442558
{
25452559
caseRELPERSISTENCE_UNLOGGED:
25462560
caseRELPERSISTENCE_PERMANENT:
25472561
rel->rd_backend=InvalidBackendId;
2562+
rel->rd_islocaltemp= false;
25482563
break;
25492564
caseRELPERSISTENCE_TEMP:
2565+
Assert(isTempOrToastNamespace(relnamespace));
25502566
rel->rd_backend=MyBackendId;
2567+
rel->rd_islocaltemp= true;
25512568
break;
25522569
default:
25532570
elog(ERROR,"invalid relpersistence: %c",relpersistence);

‎src/include/utils/rel.h

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ typedef struct RelationData
8181
structSMgrRelationData*rd_smgr;/* cached file handle, or NULL */
8282
intrd_refcnt;/* reference count */
8383
BackendIdrd_backend;/* owning backend id, if temporary relation */
84+
boolrd_islocaltemp;/* rel is a temp rel of this session */
8485
boolrd_isnailed;/* rel is nailed in cache */
8586
boolrd_isvalid;/* relcache entry is valid */
8687
charrd_indexvalid;/* state of rd_indexlist: 0 = not valid, 1 =
@@ -362,22 +363,16 @@ typedef struct StdRdOptions
362363
#defineRelationUsesLocalBuffers(relation) \
363364
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
364365

365-
/*
366-
* RelationUsesTempNamespace
367-
*True if relation's catalog entries live in a private namespace.
368-
*/
369-
#defineRelationUsesTempNamespace(relation) \
370-
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP)
371-
372366
/*
373367
* RELATION_IS_LOCAL
374368
*If a rel is either temp or newly created in the current transaction,
375-
*it can be assumed to be visible only to the current backend.
369+
*it can be assumed to be accessible only to the current backend.
370+
*This is typically used to decide that we can skip acquiring locks.
376371
*
377372
* Beware of multiple eval of argument
378373
*/
379374
#defineRELATION_IS_LOCAL(relation) \
380-
((relation)->rd_backend == MyBackendId || \
375+
((relation)->rd_islocaltemp || \
381376
(relation)->rd_createSubid != InvalidSubTransactionId)
382377

383378
/*
@@ -387,8 +382,8 @@ typedef struct StdRdOptions
387382
* Beware of multiple eval of argument
388383
*/
389384
#defineRELATION_IS_OTHER_TEMP(relation) \
390-
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP \
391-
&&(relation)->rd_backend != MyBackendId)
385+
((relation)->rd_rel->relpersistence == RELPERSISTENCE_TEMP&&\
386+
!(relation)->rd_islocaltemp)
392387

393388
/* routines in utils/cache/relcache.c */
394389
externvoidRelationIncrementReferenceCount(Relationrel);

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp