@@ -703,8 +703,8 @@ OldSerXidInit(void)
703703 * Set up SLRU management of the pg_serial data.
704704 */
705705OldSerXidSlruCtl -> PagePrecedes = OldSerXidPagePrecedesLogically ;
706- SimpleLruInit (OldSerXidSlruCtl ,"OldSerXid SLRU Ctl" ,NUM_OLDSERXID_BUFFERS , 0 ,
707- OldSerXidLock ,"pg_serial" );
706+ SimpleLruInit (OldSerXidSlruCtl ,"OldSerXid SLRU Ctl" ,
707+ NUM_OLDSERXID_BUFFERS , 0 , OldSerXidLock ,"pg_serial" );
708708/* Override default assumption that writes should be fsync'd */
709709OldSerXidSlruCtl -> do_fsync = false;
710710
@@ -2954,7 +2954,8 @@ PredicateLockPageCombine(const Relation relation, const BlockNumber oldblkno,
29542954}
29552955
29562956/*
2957- * Walk the hash table and find the new xmin.
2957+ * Walk the list of in-progress serializable transactions and find the new
2958+ * xmin.
29582959 */
29592960static void
29602961SetNewSxactGlobalXmin (void )
@@ -3126,6 +3127,10 @@ ReleasePredicateLocks(const bool isCommit)
31263127&& !SxactIsReadOnly (MySerializableXact )
31273128&& SxactHasSummaryConflictOut (MySerializableXact ))
31283129{
3130+ /*
3131+ * we don't know which old committed transaction we conflicted with,
3132+ * so be conservative and use FirstNormalSerCommitSeqNo here
3133+ */
31293134MySerializableXact -> SeqNo .earliestOutConflictCommit =
31303135FirstNormalSerCommitSeqNo ;
31313136MySerializableXact -> flags |=SXACT_FLAG_CONFLICT_OUT ;
@@ -3320,14 +3325,19 @@ ReleasePredicateLocksIfROSafe(void)
33203325}
33213326
33223327/*
3323- * Clear old predicate locks.
3328+ * Clear old predicate locks, belonging to committed transactions that are no
3329+ * longer interesting to any in-progress transaction.
33243330 */
33253331static void
33263332ClearOldPredicateLocks (void )
33273333{
33283334SERIALIZABLEXACT * finishedSxact ;
33293335PREDICATELOCK * predlock ;
33303336
3337+ /*
3338+ * Loop through finished transactions. They are in commit order, so we can
3339+ * stop as soon as we find one that's still interesting.
3340+ */
33313341LWLockAcquire (SerializableFinishedListLock ,LW_EXCLUSIVE );
33323342finishedSxact = (SERIALIZABLEXACT * )
33333343SHMQueueNext (FinishedSerializableTransactions ,
@@ -3346,6 +3356,10 @@ ClearOldPredicateLocks(void)
33463356|| TransactionIdPrecedesOrEquals (finishedSxact -> finishedBefore ,
33473357PredXact -> SxactGlobalXmin ))
33483358{
3359+ /*
3360+ * This transaction committed before any in-progress transaction
3361+ * took its snapshot. It's no longer interesting.
3362+ */
33493363LWLockRelease (SerializableXactHashLock );
33503364SHMQueueDelete (& (finishedSxact -> finishedLink ));
33513365ReleaseOneSerializableXact (finishedSxact , false, false);
@@ -3362,7 +3376,10 @@ ClearOldPredicateLocks(void)
33623376LWLockAcquire (SerializableXactHashLock ,LW_SHARED );
33633377}
33643378else
3379+ {
3380+ /* Still interesting. */
33653381break ;
3382+ }
33663383finishedSxact = nextSxact ;
33673384}
33683385LWLockRelease (SerializableXactHashLock );
@@ -3391,25 +3408,27 @@ ClearOldPredicateLocks(void)
33913408canDoPartialCleanup = (predlock -> commitSeqNo <=PredXact -> CanPartialClearThrough );
33923409LWLockRelease (SerializableXactHashLock );
33933410
3411+ /*
3412+ * If this lock originally belonged to an old enough transaction, we
3413+ * can release it.
3414+ */
33943415if (canDoPartialCleanup )
33953416{
33963417PREDICATELOCKTAG tag ;
3397- SHM_QUEUE * targetLink ;
33983418PREDICATELOCKTARGET * target ;
33993419PREDICATELOCKTARGETTAG targettag ;
34003420uint32 targettaghash ;
34013421LWLockId partitionLock ;
34023422
34033423tag = predlock -> tag ;
3404- targetLink = & (predlock -> targetLink );
34053424target = tag .myTarget ;
34063425targettag = target -> tag ;
34073426targettaghash = PredicateLockTargetTagHashCode (& targettag );
34083427partitionLock = PredicateLockHashPartitionLock (targettaghash );
34093428
34103429LWLockAcquire (partitionLock ,LW_EXCLUSIVE );
34113430
3412- SHMQueueDelete (targetLink );
3431+ SHMQueueDelete (& ( predlock -> targetLink ) );
34133432SHMQueueDelete (& (predlock -> xactLink ));
34143433
34153434hash_search_with_hash_value (PredicateLockHash ,& tag ,
@@ -3437,9 +3456,9 @@ ClearOldPredicateLocks(void)
34373456 * delete the transaction.
34383457 *
34393458 * When the partial flag is set, we can release all predicate locks and
3440- *out -conflict information -- we've established that there are no longer
3459+ *in -conflict information -- we've established that there are no longer
34413460 * any overlapping read write transactions for which this transaction could
3442- * matter.
3461+ * matter -- but keep the transaction entry itself and any outConflicts .
34433462 *
34443463 * When the summarize flag is set, we've run short of room for sxact data
34453464 * and must summarize to the SLRU.Predicate locks are transferred to a
@@ -3460,6 +3479,10 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
34603479Assert (SxactIsRolledBack (sxact )|| SxactIsCommitted (sxact ));
34613480Assert (LWLockHeldByMe (SerializableFinishedListLock ));
34623481
3482+ /*
3483+ * First release all the predicate locks held by this xact (or transfer
3484+ * them to OldCommittedSxact if summarize is true)
3485+ */
34633486LWLockAcquire (SerializablePredicateLockListLock ,LW_SHARED );
34643487predlock = (PREDICATELOCK * )
34653488SHMQueueNext (& (sxact -> predicateLocks ),
@@ -3545,9 +3568,9 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
35453568sxidtag .xid = sxact -> topXid ;
35463569LWLockAcquire (SerializableXactHashLock ,LW_EXCLUSIVE );
35473570
3571+ /* Release all outConflicts (unless 'partial' is true) */
35483572if (!partial )
35493573{
3550- /* Release all outConflicts. */
35513574conflict = (RWConflict )
35523575SHMQueueNext (& sxact -> outConflicts ,
35533576& sxact -> outConflicts ,
@@ -3582,9 +3605,9 @@ ReleaseOneSerializableXact(SERIALIZABLEXACT *sxact, bool partial,
35823605conflict = nextConflict ;
35833606}
35843607
3608+ /* Finally, get rid of the xid and the record of the transaction itself. */
35853609if (!partial )
35863610{
3587- /* Get rid of the xid and the record of the transaction itself. */
35883611if (sxidtag .xid != InvalidTransactionId )
35893612hash_search (SerializableXidHash ,& sxidtag ,HASH_REMOVE ,NULL );
35903613ReleasePredXact (sxact );
@@ -3844,7 +3867,8 @@ CheckForSerializableConflictOut(const bool visible, const Relation relation,
38443867}
38453868
38463869/*
3847- * Check a particular target for rw-dependency conflict in.
3870+ * Check a particular target for rw-dependency conflict in. A subroutine of
3871+ * CheckForSerializableConflictIn().
38483872 */
38493873static void
38503874CheckTargetForConflictsIn (PREDICATELOCKTARGETTAG * targettag )