Skip to content

Commit 5b965bf

Browse files
committed
Teach autovacuum how to determine whether a temp table belongs to a crashed
backend. If so, send a LOG message to the postmaster log, and if the table is beyond the vacuum-for-wraparound horizon, forcibly drop it. Per recent discussions. Perhaps we ought to back-patch this, but it probably needs to age a bit in HEAD first.
1 parent 92d1cc8 commit 5b965bf

File tree

5 files changed

+136
-69
lines changed

5 files changed

+136
-69
lines changed

src/backend/catalog/namespace.c

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
* Portions Copyright (c) 1994, Regents of the University of California
1414
*
1515
* IDENTIFICATION
16-
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.106 2008/06/19 00:46:04 alvherre Exp $
16+
* $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.107 2008/07/01 02:09:34 tgl Exp $
1717
*
1818
*-------------------------------------------------------------------------
1919
*/
@@ -2209,6 +2209,32 @@ isOtherTempNamespace(Oid namespaceId)
22092209
return isAnyTempNamespace(namespaceId);
22102210
}
22112211

2212+
/*
2213+
* GetTempNamespaceBackendId - if the given namespace is a temporary-table
2214+
* namespace (either my own, or another backend's), return the BackendId
2215+
* that owns it. Temporary-toast-table namespaces are included, too.
2216+
* If it isn't a temp namespace, return -1.
2217+
*/
2218+
int
2219+
GetTempNamespaceBackendId(Oid namespaceId)
2220+
{
2221+
int result;
2222+
char *nspname;
2223+
2224+
/* See if the namespace name starts with "pg_temp_" or "pg_toast_temp_" */
2225+
nspname = get_namespace_name(namespaceId);
2226+
if (!nspname)
2227+
return -1; /* no such namespace? */
2228+
if (strncmp(nspname, "pg_temp_", 8) == 0)
2229+
result = atoi(nspname + 8);
2230+
else if (strncmp(nspname, "pg_toast_temp_", 14) == 0)
2231+
result = atoi(nspname + 14);
2232+
else
2233+
result = -1;
2234+
pfree(nspname);
2235+
return result;
2236+
}
2237+
22122238
/*
22132239
* GetTempToastNamespace - get the OID of my temporary-toast-table namespace,
22142240
* which must already be assigned. (This is only used when creating a toast

src/backend/postmaster/autovacuum.c

Lines changed: 77 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
*
5656
*
5757
* IDENTIFICATION
58-
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.79 2008/06/05 15:47:32 alvherre Exp $
58+
* $PostgreSQL: pgsql/src/backend/postmaster/autovacuum.c,v 1.80 2008/07/01 02:09:34 tgl Exp $
5959
*
6060
*-------------------------------------------------------------------------
6161
*/
@@ -71,6 +71,7 @@
7171
#include "access/heapam.h"
7272
#include "access/transam.h"
7373
#include "access/xact.h"
74+
#include "catalog/dependency.h"
7475
#include "catalog/indexing.h"
7576
#include "catalog/namespace.h"
7677
#include "catalog/pg_autovacuum.h"
@@ -90,7 +91,7 @@
9091
#include "storage/pmsignal.h"
9192
#include "storage/proc.h"
9293
#include "storage/procarray.h"
93-
#include "storage/sinval.h"
94+
#include "storage/sinvaladt.h"
9495
#include "tcop/tcopprot.h"
9596
#include "utils/flatfiles.h"
9697
#include "utils/fmgroids.h"
@@ -275,10 +276,6 @@ static void autovac_balance_cost(void);
275276
static void do_autovacuum(void);
276277
static void FreeWorkerInfo(int code, Datum arg);
277278

278-
static void relation_check_autovac(Oid relid, Form_pg_class classForm,
279-
Form_pg_autovacuum avForm, PgStat_StatTabEntry *tabentry,
280-
List **table_oids, List **table_toast_list,
281-
List **toast_oids);
282279
static autovac_table *table_recheck_autovac(Oid relid);
283280
static void relation_needs_vacanalyze(Oid relid, Form_pg_autovacuum avForm,
284281
Form_pg_class classForm,
@@ -1912,19 +1909,16 @@ do_autovacuum(void)
19121909
PgStat_StatTabEntry *tabentry;
19131910
HeapTuple avTup;
19141911
Oid relid;
1912+
bool dovacuum;
1913+
bool doanalyze;
1914+
bool wraparound;
1915+
int backendID;
19151916

19161917
/* Consider only regular and toast tables. */
19171918
if (classForm->relkind != RELKIND_RELATION &&
19181919
classForm->relkind != RELKIND_TOASTVALUE)
19191920
continue;
19201921

1921-
/*
1922-
* Skip temp tables (i.e. those in temp namespaces). We cannot safely
1923-
* process other backends' temp tables.
1924-
*/
1925-
if (isAnyTempNamespace(classForm->relnamespace))
1926-
continue;
1927-
19281922
relid = HeapTupleGetOid(tuple);
19291923

19301924
/* Fetch the pg_autovacuum tuple for the relation, if any */
@@ -1936,8 +1930,76 @@ do_autovacuum(void)
19361930
tabentry = get_pgstat_tabentry_relid(relid, classForm->relisshared,
19371931
shared, dbentry);
19381932

1939-
relation_check_autovac(relid, classForm, avForm, tabentry,
1940-
&table_oids, &table_toast_list, &toast_oids);
1933+
/* Check if it needs vacuum or analyze */
1934+
relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
1935+
&dovacuum, &doanalyze, &wraparound);
1936+
1937+
/*
1938+
* Check if it is a temp table (presumably, of some other backend's).
1939+
* We cannot safely process other backends' temp tables.
1940+
*/
1941+
backendID = GetTempNamespaceBackendId(classForm->relnamespace);
1942+
1943+
if (backendID > 0)
1944+
{
1945+
/* We just ignore it if the owning backend is still active */
1946+
if (backendID == MyBackendId || !BackendIdIsActive(backendID))
1947+
{
1948+
/*
1949+
* We found an orphan temp table (which was probably left
1950+
* behind by a crashed backend). If it's so old as to need
1951+
* vacuum for wraparound, forcibly drop it. Otherwise just
1952+
* log a complaint.
1953+
*/
1954+
if (wraparound && classForm->relkind == RELKIND_RELATION)
1955+
{
1956+
ObjectAddress object;
1957+
1958+
ereport(LOG,
1959+
(errmsg("autovacuum: dropping orphan temp table \"%s\".\"%s\" in database \"%s\"",
1960+
get_namespace_name(classForm->relnamespace),
1961+
NameStr(classForm->relname),
1962+
get_database_name(MyDatabaseId))));
1963+
object.classId = RelationRelationId;
1964+
object.objectId = relid;
1965+
object.objectSubId = 0;
1966+
performDeletion(&object, DROP_CASCADE);
1967+
}
1968+
else
1969+
{
1970+
ereport(LOG,
1971+
(errmsg("autovacuum: found orphan temp table \"%s\".\"%s\" in database \"%s\"",
1972+
get_namespace_name(classForm->relnamespace),
1973+
NameStr(classForm->relname),
1974+
get_database_name(MyDatabaseId))));
1975+
}
1976+
}
1977+
}
1978+
else if (classForm->relkind == RELKIND_RELATION)
1979+
{
1980+
/* Plain relations that need work are added to table_oids */
1981+
if (dovacuum || doanalyze)
1982+
table_oids = lappend_oid(table_oids, relid);
1983+
else if (OidIsValid(classForm->reltoastrelid))
1984+
{
1985+
/*
1986+
* If it doesn't appear to need vacuuming, but it has a toast
1987+
* table, remember the association to revisit below.
1988+
*/
1989+
av_relation *rel = palloc(sizeof(av_relation));
1990+
1991+
rel->ar_relid = relid;
1992+
rel->ar_toastrelid = classForm->reltoastrelid;
1993+
1994+
table_toast_list = lappend(table_toast_list, rel);
1995+
}
1996+
}
1997+
else
1998+
{
1999+
/* TOAST relations that need vacuum are added to toast_oids */
2000+
if (dovacuum)
2001+
toast_oids = lappend_oid(toast_oids, relid);
2002+
}
19412003

19422004
if (HeapTupleIsValid(avTup))
19432005
heap_freetuple(avTup);
@@ -2231,56 +2293,6 @@ get_pgstat_tabentry_relid(Oid relid, bool isshared, PgStat_StatDBEntry *shared,
22312293
return tabentry;
22322294
}
22332295

2234-
/*
2235-
* relation_check_autovac
2236-
*
2237-
* For a given relation (either a plain table or TOAST table), check whether it
2238-
* needs vacuum or analyze.
2239-
*
2240-
* Plain tables that need either are added to the table_list. TOAST tables
2241-
* that need vacuum are added to toast_list. Plain tables that don't need
2242-
* either but which have a TOAST table are added, as a struct, to
2243-
* table_toast_list. The latter is to allow appending the OIDs of the plain
2244-
* tables whose TOAST table needs vacuuming into the plain tables list, which
2245-
* allows us to substantially reduce the number of "rechecks" that we need to
2246-
* do later on.
2247-
*/
2248-
static void
2249-
relation_check_autovac(Oid relid, Form_pg_class classForm,
2250-
Form_pg_autovacuum avForm, PgStat_StatTabEntry *tabentry,
2251-
List **table_oids, List **table_toast_list,
2252-
List **toast_oids)
2253-
{
2254-
bool dovacuum;
2255-
bool doanalyze;
2256-
bool dummy;
2257-
2258-
relation_needs_vacanalyze(relid, avForm, classForm, tabentry,
2259-
&dovacuum, &doanalyze, &dummy);
2260-
2261-
if (classForm->relkind == RELKIND_TOASTVALUE)
2262-
{
2263-
if (dovacuum)
2264-
*toast_oids = lappend_oid(*toast_oids, relid);
2265-
}
2266-
else
2267-
{
2268-
Assert(classForm->relkind == RELKIND_RELATION);
2269-
2270-
if (dovacuum || doanalyze)
2271-
*table_oids = lappend_oid(*table_oids, relid);
2272-
else if (OidIsValid(classForm->reltoastrelid))
2273-
{
2274-
av_relation *rel = palloc(sizeof(av_relation));
2275-
2276-
rel->ar_relid = relid;
2277-
rel->ar_toastrelid = classForm->reltoastrelid;
2278-
2279-
*table_toast_list = lappend(*table_toast_list, rel);
2280-
}
2281-
}
2282-
}
2283-
22842296
/*
22852297
* table_recheck_autovac
22862298
*

src/backend/storage/ipc/sinvaladt.c

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.72 2008/06/20 00:24:53 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/ipc/sinvaladt.c,v 1.73 2008/07/01 02:09:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -357,6 +357,33 @@ CleanupInvalidationState(int status, Datum arg)
357357
LWLockRelease(SInvalWriteLock);
358358
}
359359

360+
/*
361+
* BackendIdIsActive
362+
* Test if the given backend ID is currently assigned to a process.
363+
*/
364+
bool
365+
BackendIdIsActive(int backendID)
366+
{
367+
bool result;
368+
SISeg *segP = shmInvalBuffer;
369+
370+
/* Need to lock out additions/removals of backends */
371+
LWLockAcquire(SInvalWriteLock, LW_SHARED);
372+
373+
if (backendID > 0 && backendID <= segP->lastBackend)
374+
{
375+
ProcState *stateP = &segP->procState[backendID - 1];
376+
377+
result = (stateP->procPid != 0);
378+
}
379+
else
380+
result = false;
381+
382+
LWLockRelease(SInvalWriteLock);
383+
384+
return result;
385+
}
386+
360387
/*
361388
* SIInsertDataEntries
362389
* Add new invalidation message(s) to the buffer.

src/include/catalog/namespace.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.53 2008/01/01 19:45:56 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/catalog/namespace.h,v 1.54 2008/07/01 02:09:34 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -95,6 +95,7 @@ extern bool isTempToastNamespace(Oid namespaceId);
9595
extern bool isTempOrToastNamespace(Oid namespaceId);
9696
extern bool isAnyTempNamespace(Oid namespaceId);
9797
extern bool isOtherTempNamespace(Oid namespaceId);
98+
extern int GetTempNamespaceBackendId(Oid namespaceId);
9899
extern Oid GetTempToastNamespace(void);
99100
extern void ResetTempTableNamespace(void);
100101

src/include/storage/sinvaladt.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
1616
* Portions Copyright (c) 1994, Regents of the University of California
1717
*
18-
* $PostgreSQL: pgsql/src/include/storage/sinvaladt.h,v 1.48 2008/06/19 21:32:56 tgl Exp $
18+
* $PostgreSQL: pgsql/src/include/storage/sinvaladt.h,v 1.49 2008/07/01 02:09:34 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -30,6 +30,7 @@
3030
extern Size SInvalShmemSize(void);
3131
extern void CreateSharedInvalidationState(void);
3232
extern void SharedInvalBackendInit(void);
33+
extern bool BackendIdIsActive(int backendID);
3334

3435
extern void SIInsertDataEntries(const SharedInvalidationMessage *data, int n);
3536
extern int SIGetDataEntries(SharedInvalidationMessage *data, int datasize);

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