reset_temp_schema_v3.patch
text/x-diff
Filename: reset_temp_schema_v3.patch
Type: text/x-diff
Part: 0
Patch
Format: unified
Series: patch v3
| File | + | − |
|---|---|---|
| src/backend/catalog/namespace.c | 62 | 1 |
| src/backend/postmaster/autovacuum.c | 7 | 12 |
| src/backend/storage/lmgr/proc.c | 2 | 0 |
| src/include/catalog/namespace.h | 1 | 0 |
| src/include/storage/proc.h | 3 | 0 |
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 0f67a122ed..0630032148 100644
--- a/src/backend/catalog/namespace.c
+++ b/src/backend/catalog/namespace.c
@@ -47,7 +47,7 @@
#include "parser/parse_func.h"
#include "storage/ipc.h"
#include "storage/lmgr.h"
-#include "storage/sinval.h"
+#include "storage/sinvaladt.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
@@ -3204,6 +3204,42 @@ isOtherTempNamespace(Oid namespaceId)
return isAnyTempNamespace(namespaceId);
}
+/*
+ * isTempNamespaceInUse - is the given namespace owned and actively used
+ * by a backend?
+ *
+ * Note: this is used by autovacuum to detect the presence of orphaned
+ * temporary tables, based on the active namespace tracked by PGPROC entries.
+ */
+bool
+isTempNamespaceInUse(Oid namespaceId)
+{
+ PGPROC *proc;
+ int backendId;
+
+ backendId = GetTempNamespaceBackendId(namespaceId);
+
+ if (backendId == InvalidBackendId ||
+ backendId == MyBackendId)
+ return false;
+
+ /* Is the backend alive? */
+ proc = BackendIdGetProc(backendId);
+ if (proc == NULL)
+ return false;
+
+ /* Is the backend connected to the database being vacuumed? */
+ if (proc->databaseId != MyDatabaseId)
+ return false;
+
+ /* Does the backend own the temporary namespace? */
+ if (proc->tempNamespaceId != namespaceId)
+ return false;
+
+ /* all good to go */
+ return true;
+}
+
/*
* GetTempNamespaceBackendId - if the given namespace is a temporary-table
* namespace (either my own, or another backend's), return the BackendId
@@ -3893,6 +3929,15 @@ InitTempTableNamespace(void)
myTempNamespace = namespaceId;
myTempToastNamespace = toastspaceId;
+ /*
+ * Mark the proc entry as owning this namespace which autovacuum uses to
+ * decide if a temporary file entry can be marked as orphaned or not. Even
+ * if this is an atomic operation, this can be safely done lock-less as no
+ * temporary relations associated to it can be seen yet by autovacuum when
+ * scanning pg_class.
+ */
+ MyProc->tempNamespaceId = namespaceId;
+
/* It should not be done already. */
AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
myTempNamespaceSubID = GetCurrentSubTransactionId();
@@ -3923,6 +3968,14 @@ AtEOXact_Namespace(bool isCommit, bool parallel)
myTempNamespace = InvalidOid;
myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in the proc entry. The
+ * creation of the temporary namespace has failed for some reason
+ * and cannot be seen by autovacuum as it has not been committed,
+ * hence it is fine to do this in a lock-less fashion.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
}
myTempNamespaceSubID = InvalidSubTransactionId;
}
@@ -3975,6 +4028,14 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
myTempNamespace = InvalidOid;
myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in the proc entry. The
+ * creation of the temporary namespace has failed for some reason
+ * and cannot be seen by autovacuum as it has not been committed,
+ * hence it is fine to do this in a lock-less fashion.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
}
}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1d9cfc63d2..9f45ffcea3 100644
--- a/src/backend/postmaster/autovacuum.c
+++ b/src/backend/postmaster/autovacuum.c
@@ -2080,14 +2080,11 @@ do_autovacuum(void)
*/
if (classForm->relpersistence == RELPERSISTENCE_TEMP)
{
- int backendID;
-
- backendID = GetTempNamespaceBackendId(classForm->relnamespace);
-
- /* We just ignore it if the owning backend is still active */
- if (backendID != InvalidBackendId &&
- (backendID == MyBackendId ||
- BackendIdGetProc(backendID) == NULL))
+ /*
+ * We just ignore it if the owning backend is still active and
+ * using the temporary schema.
+ */
+ if (!isTempNamespaceInUse(classForm->relnamespace))
{
/*
* The table seems to be orphaned -- although it might be that
@@ -2257,10 +2254,8 @@ do_autovacuum(void)
UnlockRelationOid(relid, AccessExclusiveLock);
continue;
}
- backendID = GetTempNamespaceBackendId(classForm->relnamespace);
- if (!(backendID != InvalidBackendId &&
- (backendID == MyBackendId ||
- BackendIdGetProc(backendID) == NULL)))
+
+ if (isTempNamespaceInUse(classForm->relnamespace))
{
UnlockRelationOid(relid, AccessExclusiveLock);
continue;
diff --git a/src/backend/storage/lmgr/proc.c b/src/backend/storage/lmgr/proc.c
index 6f30e082b2..6f9aaa52fa 100644
--- a/src/backend/storage/lmgr/proc.c
+++ b/src/backend/storage/lmgr/proc.c
@@ -371,6 +371,7 @@ InitProcess(void)
MyProc->backendId = InvalidBackendId;
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
+ MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker;
MyPgXact->delayChkpt = false;
MyPgXact->vacuumFlags = 0;
@@ -552,6 +553,7 @@ InitAuxiliaryProcess(void)
MyProc->backendId = InvalidBackendId;
MyProc->databaseId = InvalidOid;
MyProc->roleId = InvalidOid;
+ MyProc->tempNamespaceId = InvalidOid;
MyProc->isBackgroundWorker = IsBackgroundWorker;
MyPgXact->delayChkpt = false;
MyPgXact->vacuumFlags = 0;
diff --git a/src/include/catalog/namespace.h b/src/include/catalog/namespace.h
index 7991de5e21..0e202372d5 100644
--- a/src/include/catalog/namespace.h
+++ b/src/include/catalog/namespace.h
@@ -137,6 +137,7 @@ extern bool isTempToastNamespace(Oid namespaceId);
extern bool isTempOrTempToastNamespace(Oid namespaceId);
extern bool isAnyTempNamespace(Oid namespaceId);
extern bool isOtherTempNamespace(Oid namespaceId);
+extern bool isTempNamespaceInUse(Oid namespaceId);
extern int GetTempNamespaceBackendId(Oid namespaceId);
extern Oid GetTempToastNamespace(void);
extern void GetTempNamespaceState(Oid *tempNamespaceId,
diff --git a/src/include/storage/proc.h b/src/include/storage/proc.h
index 5c19a61dcf..cb613c8076 100644
--- a/src/include/storage/proc.h
+++ b/src/include/storage/proc.h
@@ -114,6 +114,9 @@ struct PGPROC
Oid databaseId; /* OID of database this backend is using */
Oid roleId; /* OID of role using this backend */
+ Oid tempNamespaceId; /* OID of temp schema this backend is
+ * using */
+
bool isBackgroundWorker; /* true if background worker. */
/*