aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/access/transam/twophase.c1
-rw-r--r--src/backend/catalog/namespace.c70
-rw-r--r--src/backend/postmaster/autovacuum.c20
-rw-r--r--src/backend/storage/lmgr/proc.c2
4 files changed, 79 insertions, 14 deletions
diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c
index 0ae07227941..4aff6cf7f27 100644
--- a/src/backend/access/transam/twophase.c
+++ b/src/backend/access/transam/twophase.c
@@ -471,6 +471,7 @@ MarkAsPreparingGuts(GlobalTransaction gxact, TransactionId xid, const char *gid,
proc->backendId = InvalidBackendId;
proc->databaseId = databaseid;
proc->roleId = owner;
+ proc->tempNamespaceId = InvalidOid;
proc->isBackgroundWorker = false;
proc->lwWaiting = false;
proc->lwWaitMode = 0;
diff --git a/src/backend/catalog/namespace.c b/src/backend/catalog/namespace.c
index 0f67a122ede..3971346e738 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"
@@ -3205,6 +3205,46 @@ isOtherTempNamespace(Oid namespaceId)
}
/*
+ * isTempNamespaceInUse - is the given namespace owned and actively used
+ * by a backend?
+ *
+ * Note: this can be used while scanning relations in pg_class to detect
+ * orphaned temporary tables or namespaces with a backend connected to a
+ * given database. The result may be out of date quickly, so the caller
+ * must be careful how to handle this information.
+ */
+bool
+isTempNamespaceInUse(Oid namespaceId)
+{
+ PGPROC *proc;
+ int backendId;
+
+ Assert(OidIsValid(MyDatabaseId));
+
+ 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 same database we are looking at? */
+ 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
* that owns it. Temporary-toast-table namespaces are included, too.
@@ -3893,6 +3933,16 @@ InitTempTableNamespace(void)
myTempNamespace = namespaceId;
myTempToastNamespace = toastspaceId;
+ /*
+ * Mark MyProc as owning this namespace which other processes can use to
+ * decide if a temporary namespace is in use or not. We assume that
+ * assignment of namespaceId is an atomic operation. Even if it is not,
+ * the temporary relation which resulted in the creation of this temporary
+ * namespace is still locked until the current transaction commits, so it
+ * would not be accessible yet, acting as a barrier.
+ */
+ MyProc->tempNamespaceId = namespaceId;
+
/* It should not be done already. */
AssertState(myTempNamespaceSubID == InvalidSubTransactionId);
myTempNamespaceSubID = GetCurrentSubTransactionId();
@@ -3923,6 +3973,15 @@ AtEOXact_Namespace(bool isCommit, bool parallel)
myTempNamespace = InvalidOid;
myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in MyProc. We assume that
+ * this operation is atomic. Even if it is not, the temporary
+ * table which created this namespace is still locked until this
+ * transaction aborts so it would not be visible yet, acting as a
+ * barrier.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
}
myTempNamespaceSubID = InvalidSubTransactionId;
}
@@ -3975,6 +4034,15 @@ AtEOSubXact_Namespace(bool isCommit, SubTransactionId mySubid,
myTempNamespace = InvalidOid;
myTempToastNamespace = InvalidOid;
baseSearchPathValid = false; /* need to rebuild list */
+
+ /*
+ * Reset the temporary namespace flag in MyProc. We assume that
+ * this operation is atomic. Even if it is not, the temporary
+ * table which created this namespace is still locked until this
+ * transaction aborts so it would not be visible yet, acting as a
+ * barrier.
+ */
+ MyProc->tempNamespaceId = InvalidOid;
}
}
diff --git a/src/backend/postmaster/autovacuum.c b/src/backend/postmaster/autovacuum.c
index 1d9cfc63d22..978089575b8 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
@@ -2215,7 +2212,6 @@ do_autovacuum(void)
{
Oid relid = lfirst_oid(cell);
Form_pg_class classForm;
- int backendID;
ObjectAddress object;
/*
@@ -2257,10 +2253,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 6f30e082b26..6f9aaa52faf 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;