3737 *
3838 *
3939 * IDENTIFICATION
40- * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.64 2010/04/19 18:03:38 sriggs Exp $
40+ * $PostgreSQL: pgsql/src/backend/storage/ipc/procarray.c,v 1.65 2010/04/21 19:08:14 sriggs Exp $
4141 *
4242 *-------------------------------------------------------------------------
4343 */
@@ -1638,58 +1638,23 @@ GetCurrentVirtualXIDs(TransactionId limitXmin, bool excludeXmin0,
16381638 * limitXmin is supplied as either latestRemovedXid, or InvalidTransactionId
16391639 * in cases where we cannot accurately determine a value for latestRemovedXid.
16401640 *
1641- * If limitXmin is InvalidTransactionId then we are forced to assume that
1642- * latest xid that might have caused a cleanup record will be
1643- * latestCompletedXid, so we set limitXmin to be latestCompletedXid instead.
1644- * We then skip any backends with xmin > limitXmin. This means that
1645- * cleanup records don't conflict with some recent snapshots.
1646- *
1647- * The reason for using latestCompletedxid is that we aren't certain which
1648- * of the xids in KnownAssignedXids are actually FATAL errors that did
1649- * not write abort records. In almost every case they won't be, but we
1650- * don't know that for certain. So we need to conflict with all current
1651- * snapshots whose xmin is less than latestCompletedXid to be safe. This
1652- * causes false positives in our assessment of which vxids conflict.
1653- *
1654- * By using exclusive lock we prevent new snapshots from being taken while
1655- * we work out which snapshots to conflict with. This protects those new
1656- * snapshots from also being included in our conflict list.
1657- *
1658- * After the lock is released, we allow snapshots again. It is possible
1659- * that we arrive at a snapshot that is identical to one that we just
1660- * decided we should conflict with. This a case of false positives, not an
1661- * actual problem.
1662- *
1663- * There are two cases: (1) if we were correct in using latestCompletedXid
1664- * then that means that all xids in the snapshot lower than that are FATAL
1665- * errors, so not xids that ever commit. We can make no visibility errors
1666- * if we allow such xids into the snapshot. (2) if we erred on the side of
1667- * caution and in fact the latestRemovedXid should have been earlier than
1668- * latestCompletedXid then we conflicted with a snapshot needlessly. Taking
1669- * another identical snapshot is OK, because the earlier conflicted
1670- * snapshot was a false positive.
1671- *
1672- * In either case, a snapshot taken after conflict assessment will still be
1673- * valid and non-conflicting even if an identical snapshot that existed
1674- * before conflict assessment was assessed as conflicting.
1675- *
1676- * If we allowed concurrent snapshots while we were deciding who to
1677- * conflict with we would need to include all concurrent snapshotters in
1678- * the conflict list as well. We'd have difficulty in working out exactly
1679- * who that was, so it is happier for all concerned if we take an exclusive
1680- * lock. Notice that we only hold that lock for as long as it takes to
1681- * make the conflict list, not for the whole duration of the conflict
1682- * resolution.
1683- *
1684- * It also means that users waiting for a snapshot is a good thing, since
1685- * it is more likely that they will live longer after having waited. So it
1686- * is a benefit, not an oversight that we use exclusive lock here.
1687- *
1688- * We replace InvalidTransactionId with latestCompletedXid here because
1689- * this is the most convenient place to do that, while we hold ProcArrayLock.
1690- * The originator of the cleanup record wanted to avoid checking the value of
1691- * latestCompletedXid since doing so would be a performance issue during
1692- * normal running, so we check it essentially for free on the standby.
1641+ * If limitXmin is InvalidTransactionId then we want to kill everybody,
1642+ * so we're not worried if they have a snapshot or not, nor does it really
1643+ * matter what type of lock we hold.
1644+ *
1645+ * All callers that are checking xmins always now supply a valid and useful
1646+ * value for limitXmin. The limitXmin is always lower than the lowest
1647+ * numbered KnownAssignedXid that is not already a FATAL error. This is
1648+ * because we only care about cleanup records that are cleaning up tuple
1649+ * versions from committed transactions. In that case they will only occur
1650+ * at the point where the record is less than the lowest running xid. That
1651+ * allows us to say that if any backend takes a snapshot concurrently with
1652+ * us then the conflict assessment made here would never include the snapshot
1653+ * that is being derived. So we take LW_SHARED on the ProcArray and allow
1654+ * concurrent snapshots when limitXmin is valid. We might think about adding
1655+ * Assert(limitXmin < lowest(KnownAssignedXids))
1656+ * but that would not be true in the case of FATAL errors lagging in array,
1657+ * but we already know those are bogus anyway, so we skip that test.
16931658 *
16941659 * If dbOid is valid we skip backends attached to other databases.
16951660 *
@@ -1719,14 +1684,7 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
17191684errmsg ("out of memory" )));
17201685}
17211686
1722- LWLockAcquire (ProcArrayLock ,LW_EXCLUSIVE );
1723-
1724- /*
1725- * If we don't know the TransactionId that created the conflict, set it to
1726- * latestCompletedXid which is the latest possible value.
1727- */
1728- if (!TransactionIdIsValid (limitXmin ))
1729- limitXmin = ShmemVariableCache -> latestCompletedXid ;
1687+ LWLockAcquire (ProcArrayLock ,LW_SHARED );
17301688
17311689for (index = 0 ;index < arrayP -> numProcs ;index ++ )
17321690{
@@ -1747,7 +1705,8 @@ GetConflictingVirtualXIDs(TransactionId limitXmin, Oid dbOid)
17471705 * no snapshot and cannot get another one while we hold exclusive
17481706 * lock.
17491707 */
1750- if (TransactionIdIsValid (pxmin )&& !TransactionIdFollows (pxmin ,limitXmin ))
1708+ if (!TransactionIdIsValid (limitXmin )||
1709+ (TransactionIdIsValid (pxmin )&& !TransactionIdFollows (pxmin ,limitXmin )))
17511710{
17521711VirtualTransactionId vxid ;
17531712