diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-11-17 18:00:15 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-11-17 18:00:15 +0000 |
| commit | 4f335a3d7fda4b4a0efd4568ac61d036098d951a (patch) | |
| tree | 76277f2c8c5abc7e61967fc3fb828f7a2afe1bf5 /src/backend/access/transam | |
| parent | b6b5aa102b3e53742a59e686ef58f382159ec3c0 (diff) | |
| download | postgresql-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.c | 51 |
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. * |
