summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera2018-12-27 19:17:40 +0000
committerAlvaro Herrera2018-12-27 19:17:40 +0000
commitaa2e84d2cc8dd08f3531a1f36eaa0490117e5baa (patch)
tree2bdf000f944b50144428643e8e8dbf12ee04c805
parent7fc2363a615842e42f927d915331a4b3bd67af19 (diff)
Have DISCARD ALL/TEMP remove leftover temp tables
Previously, it would only remove temp tables created in the same session; but if the session uses the BackendId of a previously crashed backend that left temp tables around, those would not get removed. Since autovacuum would not drop them either (because it sees that the BackendId is in use by the current session) these can cause annoying xid-wraparound warnings. Apply to branches 9.4 to 10. This is not a problem since version 11, because commit 943576bddcb5 added state tracking that makes autovacuum realize that those temp tables are not ours, so it removes them. This is useful to handle in DISCARD, because even though it does not handle all situations, it does handle the common one where a connection pooler keeps the same session open for an indefinitely long time. Discussion: https://postgr.es/m/20181226190834.wsk2wzott5yzrjiq@alvherre.pgsql Reviewed-by: Takayuki Tsunakawa, Michaƫl Paquier
-rw-r--r--src/backend/catalog/namespace.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 8092381ae5c..193c3dadbf2 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -3902,12 +3902,31 @@ RemoveTempRelationsCallback(int code, Datum arg)
/*
* Remove all temp tables from the temporary namespace.
+ *
+ * If we haven't set up one yet, but one exists from a previous crashed
+ * backend, clean that one; but only do this once in a session's life.
*/
void
ResetTempTableNamespace(void)
{
+ static bool TempNamespaceCleaned = false;
+
if (OidIsValid(myTempNamespace))
RemoveTempRelations(myTempNamespace);
+ else if (MyBackendId != InvalidBackendId && !RecoveryInProgress() &&
+ !TempNamespaceCleaned)
+ {
+ char namespaceName[NAMEDATALEN];
+ Oid namespaceId;
+
+ snprintf(namespaceName, sizeof(namespaceName), "pg_temp_%d",
+ MyBackendId);
+ namespaceId = get_namespace_oid(namespaceName, true);
+ if (OidIsValid(namespaceId))
+ RemoveTempRelations(namespaceId);
+ }
+
+ TempNamespaceCleaned = true;
}