On 08.03.2011 02:37, YAMAMOTO Takashi wrote:

The following bug has been logged online:

Bug reference:      5918
Logged by:          YAMAMOTO Takashi
Email address:      y...@mwd.biglobe.ne.jp
PostgreSQL version: 9.1devel
Operating system:   NetBSD
Description:        SummarizeOldestCommittedSxact assertion failure
Details:

running 05d93c38a791836eeceaf8edb0ea8cb19cdf2760 with my patch
in BUG #5915 applied, i got the following assertion failure.
given that availableList is not empty and SxactGlobalXminCount == 0,
i guess it was raced with ReleasePredicateLocks.

Yeah, that's what it looks like. One backend calls RegisterSerializableTransaction() while all the serializablexact slots are in use. So it releases SerializableXactHashLock and calls SummarizeOldestCommittedSxact(). Before SummarizeOldestCommittedSxact() acquires SerializableFinishedListLock, another backend calls ReleasePredicateLocks(false), triggering cleanup of old predicate locks, and ClearOldPredicateLocks() clears all old locks. Now when SummarizeOldestCommittedSxact() finally gets the lock, it sees that there are no old transactions to summarize, and trips the assertion.

I think we need to just treat an empty list as normal in SummarizeOldestcommittedSxact(), patch attached.

Thanks for yet another excellent bug report!

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
diff --git a/src/backend/storage/lmgr/predicate.c b/src/backend/storage/lmgr/predicate.c
index 700c0db..a8af31e 100644
--- a/src/backend/storage/lmgr/predicate.c
+++ b/src/backend/storage/lmgr/predicate.c
@@ -1301,15 +1301,21 @@ SummarizeOldestCommittedSxact(void)
 
 	LWLockAcquire(SerializableFinishedListLock, LW_EXCLUSIVE);
 
-#ifdef TEST_OLDSERXID
+	/*
+	 * This function is only called if there are no sxact slots available.
+	 * Some of them must belong to old, already-finished transactions, so
+	 * there should be something in FinishedSerializableTransactions list
+	 * that we can summarize. However, there's a race condition: while we
+	 * were not holding any locks, a transaction might have ended and cleaned
+	 * up all the finished sxact entries already, freeing up their sxact
+	 * slots. In that case, we have nothing to do here. The caller will find
+	 * one of the slots released by the other backend when it retries.
+	 */
 	if (SHMQueueEmpty(FinishedSerializableTransactions))
 	{
 		LWLockRelease(SerializableFinishedListLock);
 		return;
 	}
-#else
-	Assert(!SHMQueueEmpty(FinishedSerializableTransactions));
-#endif
 
 	/*
 	 * Grab the first sxact off the finished list -- this will be the earliest
-- 
Sent via pgsql-bugs mailing list (pgsql-bugs@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-bugs

Reply via email to