Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 65e388d

Browse files
committed
Fix race in SERIALIZABLE READ ONLY.
Commit bdaabb9 started skipping doomed transactions when building the list of possible conflicts for SERIALIZABLE READ ONLY. That makes sense, because doomed transactions won't commit, but a couple of subtle things broke: 1. If all uncommitted r/w transactions are doomed, a READ ONLY transaction would arbitrarily not benefit from the safe snapshot optimization. It would not be taken immediately, and yet no other transaction would set SXACT_FLAG_RO_SAFE later. 2. In the same circumstances but with DEFERRABLE, GetSafeSnapshot() would correctly exit its wait loop without sleeping and then take the optimization in non-assert builds, but assert builds would fail a sanity check that SXACT_FLAG_RO_SAFE had been set by another transaction. This is similar to the case for PredXact->WritableSxactCount == 0. We should opt out immediately if our possibleUnsafeConflicts list is empty after filtering. The code to maintain the serializable global xmin is moved down below the new opt out site, because otherwise we'd have to reverse its effects before returning. Back-patch to all supported releases. Bug #17368. Reported-by: Alexander Lakhin <exclusion@gmail.com> Discussion: https://postgr.es/m/17116-d6ca217acc180e30%40postgresql.org Discussion: https://postgr.es/m/20110707212159.GF76634%40csail.mit.edu
1 parent 8bf8265 commit 65e388d

File tree

1 file changed

+31
-18
lines changed

1 file changed

+31
-18
lines changed

src/backend/storage/lmgr/predicate.c

+31-18
Original file line numberDiff line numberDiff line change
@@ -1782,24 +1782,6 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
17821782
return snapshot;
17831783
}
17841784

1785-
/* Maintain serializable global xmin info. */
1786-
if (!TransactionIdIsValid(PredXact->SxactGlobalXmin))
1787-
{
1788-
Assert(PredXact->SxactGlobalXminCount == 0);
1789-
PredXact->SxactGlobalXmin = snapshot->xmin;
1790-
PredXact->SxactGlobalXminCount = 1;
1791-
SerialSetActiveSerXmin(snapshot->xmin);
1792-
}
1793-
else if (TransactionIdEquals(snapshot->xmin, PredXact->SxactGlobalXmin))
1794-
{
1795-
Assert(PredXact->SxactGlobalXminCount > 0);
1796-
PredXact->SxactGlobalXminCount++;
1797-
}
1798-
else
1799-
{
1800-
Assert(TransactionIdFollows(snapshot->xmin, PredXact->SxactGlobalXmin));
1801-
}
1802-
18031785
/* Initialize the structure. */
18041786
sxact->vxid = vxid;
18051787
sxact->SeqNo.lastCommitBeforeSnapshot = PredXact->LastSxactCommitSeqNo;
@@ -1839,6 +1821,19 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
18391821
SetPossibleUnsafeConflict(sxact, othersxact);
18401822
}
18411823
}
1824+
1825+
/*
1826+
* If we didn't find any possibly unsafe conflicts because every
1827+
* uncommitted writable transaction turned out to be doomed, then we
1828+
* can "opt out" immediately. See comments above the earlier check for
1829+
* PredXact->WritableSxactCount == 0.
1830+
*/
1831+
if (dlist_is_empty(&sxact->possibleUnsafeConflicts))
1832+
{
1833+
ReleasePredXact(sxact);
1834+
LWLockRelease(SerializableXactHashLock);
1835+
return snapshot;
1836+
}
18421837
}
18431838
else
18441839
{
@@ -1847,6 +1842,24 @@ GetSerializableTransactionSnapshotInt(Snapshot snapshot,
18471842
(MaxBackends + max_prepared_xacts));
18481843
}
18491844

1845+
/* Maintain serializable global xmin info. */
1846+
if (!TransactionIdIsValid(PredXact->SxactGlobalXmin))
1847+
{
1848+
Assert(PredXact->SxactGlobalXminCount == 0);
1849+
PredXact->SxactGlobalXmin = snapshot->xmin;
1850+
PredXact->SxactGlobalXminCount = 1;
1851+
SerialSetActiveSerXmin(snapshot->xmin);
1852+
}
1853+
else if (TransactionIdEquals(snapshot->xmin, PredXact->SxactGlobalXmin))
1854+
{
1855+
Assert(PredXact->SxactGlobalXminCount > 0);
1856+
PredXact->SxactGlobalXminCount++;
1857+
}
1858+
else
1859+
{
1860+
Assert(TransactionIdFollows(snapshot->xmin, PredXact->SxactGlobalXmin));
1861+
}
1862+
18501863
MySerializableXact = sxact;
18511864
MyXactDidWrite = false; /* haven't written anything yet */
18521865

0 commit comments

Comments
 (0)