summaryrefslogtreecommitdiff
path: root/src/backend/access/transam
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2006-11-17 18:00:15 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2006-11-17 18:00:15 +0000
commit4f335a3d7fda4b4a0efd4568ac61d036098d951a (patch)
tree76277f2c8c5abc7e61967fc3fb828f7a2afe1bf5 /src/backend/access/transam
parentb6b5aa102b3e53742a59e686ef58f382159ec3c0 (diff)
downloadpostgresql-4f335a3d7fda4b4a0efd4568ac61d036098d951a.tar.gz
Repair two related errors in heap_lock_tuple: it was failing to recognize
cases where we already hold the desired lock "indirectly", either via membership in a MultiXact or because the lock was originally taken by a different subtransaction of the current transaction. These cases must be accounted for to avoid needless deadlocks and/or inappropriate replacement of an exclusive lock with a shared lock. Per report from Clarence Gardner and subsequent investigation.
Diffstat (limited to 'src/backend/access/transam')
-rw-r--r--src/backend/access/transam/multixact.c51
1 files changed, 45 insertions, 6 deletions
diff --git a/src/backend/access/transam/multixact.c b/src/backend/access/transam/multixact.c
index 167d65fd2d..80cb5bae3f 100644
--- a/src/backend/access/transam/multixact.c
+++ b/src/backend/access/transam/multixact.c
@@ -42,7 +42,7 @@
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.21 2006/10/04 00:29:49 momjian Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.22 2006/11/17 18:00:15 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -366,7 +366,6 @@ bool
MultiXactIdIsRunning(MultiXactId multi)
{
TransactionId *members;
- TransactionId myXid;
int nmembers;
int i;
@@ -380,12 +379,14 @@ MultiXactIdIsRunning(MultiXactId multi)
return false;
}
- /* checking for myself is cheap */
- myXid = GetTopTransactionId();
-
+ /*
+ * Checking for myself is cheap compared to looking in shared memory,
+ * so first do the equivalent of MultiXactIdIsCurrent(). This is not
+ * needed for correctness, it's just a fast path.
+ */
for (i = 0; i < nmembers; i++)
{
- if (TransactionIdEquals(members[i], myXid))
+ if (TransactionIdIsCurrentTransactionId(members[i]))
{
debug_elog3(DEBUG2, "IsRunning: I (%d) am running!", i);
pfree(members);
@@ -417,6 +418,44 @@ MultiXactIdIsRunning(MultiXactId multi)
}
/*
+ * MultiXactIdIsCurrent
+ * Returns true if the current transaction is a member of the MultiXactId.
+ *
+ * We return true if any live subtransaction of the current top-level
+ * transaction is a member. This is appropriate for the same reason that a
+ * lock held by any such subtransaction is globally equivalent to a lock
+ * held by the current subtransaction: no such lock could be released without
+ * aborting this subtransaction, and hence releasing its locks. So it's not
+ * necessary to add the current subxact to the MultiXact separately.
+ */
+bool
+MultiXactIdIsCurrent(MultiXactId multi)
+{
+ bool result = false;
+ TransactionId *members;
+ int nmembers;
+ int i;
+
+ nmembers = GetMultiXactIdMembers(multi, &members);
+
+ if (nmembers < 0)
+ return false;
+
+ for (i = 0; i < nmembers; i++)
+ {
+ if (TransactionIdIsCurrentTransactionId(members[i]))
+ {
+ result = true;
+ break;
+ }
+ }
+
+ pfree(members);
+
+ return result;
+}
+
+/*
* MultiXactIdSetOldestMember
* Save the oldest MultiXactId this transaction could be a member of.
*