On Tue, Dec 03, 2013 at 04:37:58PM +0100, Andres Freund wrote: > On 2013-12-03 10:29:54 -0500, Noah Misch wrote: > > Sorry, my original report was rather terse. I speak of the scenario > > exercised > > by the second permutation in that isolationtester spec. The multixact is > > later than VACUUM's cutoff_multi, so 9.3.1 does not freeze it at all. 9.3.2 > > does freeze it to InvalidTransactionId per the code I cited in my first > > response on this thread, which wrongly removes a key lock. > > That one is clear, I was only confused about the Assert() you > reported. But I think I've explained that elsewhere. > > I currently don't see fixing the errorneous freezing of lockers (not the > updater though) without changing the wal format or synchronously waiting > for all lockers to end. Which both see like a no-go?
Not fixing it at all is the real no-go. We'd take both of those undesirables before just tolerating the lost locks in 9.3. The attached patch illustrates the approach I was describing earlier. It fixes the test case discussed above. I haven't verified that everything else in the system is ready for it, so this is just for illustration purposes. -- Noah Misch EnterpriseDB http://www.enterprisedb.com
*** a/src/backend/access/heap/heapam.c --- b/src/backend/access/heap/heapam.c *************** *** 5384,5412 **** heap_freeze_tuple(HeapTupleHeader tuple, TransactionId cutoff_xid, TransactionId update_xid; /* ! * This is a multixact which is not marked LOCK_ONLY, but which ! * is newer than the cutoff_multi. If the update_xid is below the ! * cutoff_xid point, then we can just freeze the Xmax in the ! * tuple, removing it altogether. This seems simple, but there ! * are several underlying assumptions: ! * ! * 1. A tuple marked by an multixact containing a very old ! * committed update Xid would have been pruned away by vacuum; we ! * wouldn't be freezing this tuple at all. ! * ! * 2. There cannot possibly be any live locking members remaining ! * in the multixact. This is because if they were alive, the ! * update's Xid would had been considered, via the lockers' ! * snapshot's Xmin, as part the cutoff_xid. ! * ! * 3. We don't create new MultiXacts via MultiXactIdExpand() that ! * include a very old aborted update Xid: in that function we only ! * include update Xids corresponding to transactions that are ! * committed or in-progress. */ update_xid = HeapTupleGetUpdateXid(tuple); if (TransactionIdPrecedes(update_xid, cutoff_xid)) ! freeze_xmax = true; } } else if (TransactionIdIsNormal(xid) && --- 5384,5404 ---- TransactionId update_xid; /* ! * This is a multixact which is not marked LOCK_ONLY, but which is ! * newer than the cutoff_multi. To advance relfrozenxid, we must ! * eliminate any updater XID that falls below cutoff_xid. ! * Affected multixacts may also contain outstanding lockers, which ! * we must preserve. Forming a new multixact is tempting, but ! * solving it that way requires a WAL format change. Instead, ! * mark the tuple LOCK_ONLY. The updater XID is still present, ! * but consuming code will notice LOCK_ONLY and assume it's gone. */ update_xid = HeapTupleGetUpdateXid(tuple); if (TransactionIdPrecedes(update_xid, cutoff_xid)) ! { ! tuple->t_infomask |= HEAP_XMAX_LOCK_ONLY; ! changed = true; ! } } } else if (TransactionIdIsNormal(xid) &&
-- Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-hackers