diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2006-11-17 18:00:25 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2006-11-17 18:00:25 +0000 |
commit | 91eb4895bb6c57face2edf30e20e16e6ab942ef1 (patch) | |
tree | cfbd90e4ac556bc7e16c46b542f3e733de323375 /src/backend/access/transam/multixact.c | |
parent | a2281c8e6f5ffe4fa67584f850bfa077e526115e (diff) | |
download | postgresql-91eb4895bb6c57face2edf30e20e16e6ab942ef1.tar.gz postgresql-91eb4895bb6c57face2edf30e20e16e6ab942ef1.zip |
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/multixact.c')
-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 28750d24907..44861f323be 100644 --- a/src/backend/access/transam/multixact.c +++ b/src/backend/access/transam/multixact.c @@ -42,7 +42,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.11.2.2 2006/07/20 00:46:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/multixact.c,v 1.11.2.3 2006/11/17 18:00:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -365,7 +365,6 @@ bool MultiXactIdIsRunning(MultiXactId multi) { TransactionId *members; - TransactionId myXid; int nmembers; int i; @@ -379,12 +378,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); @@ -416,6 +417,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. * |