Skip to content

Commit 2390e52

Browse files
hyperpolymathclaude
andcommitted
proof(verisimdb): harden V10 scenario to actually exercise concurrency
Replaces the all-pairs-conflict scenario (trivially degenerates to serial execution; at most 1 ACTIVE txn) with a partial conflict graph: t1: reads {m1}, writes {m1} -- disjoint from t2 t2: reads {m2}, writes {m2} -- disjoint from t1 t3: reads {m1, m2}, writes {m3} -- conflicts with BOTH t1 and t2 This makes the reachable state graph actually contain states where two transactions (t1, t2) are simultaneously ACTIVE, so `NoConcurrentConflict` stops being vacuous and starts doing work. Verified by a throwaway `NoTwoActive` invariant: TLC produces a counter-example at depth 3 (t1 begins, t2 begins, both ACTIVE). All safety invariants (SerializabilitySafe composite) and the EveryTxnCommits liveness property still hold under this richer scenario. 33 distinct states (vs 31 under the trivial scenario; small absolute delta but qualitatively different -- the two extra states are the genuinely-concurrent (ACTIVE, ACTIVE) configurations). No config/Justfile/README changes needed; all scenario data is module-level in the .tla. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent a301cef commit 2390e52

1 file changed

Lines changed: 16 additions & 12 deletions

File tree

verisimdb/verification/proofs/tlaplus/Serializability.tla

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,23 +26,27 @@ EXTENDS Naturals, FiniteSets, Sequences, TLC
2626
\* straightforwardly model-checkable. Alternative scenarios live as separate
2727
\* .tla files.
2828
\*
29-
\* The scenario chosen: 3 transactions and 3 modalities, with pairwise
30-
\* conflicts forming a simple chain. This is the smallest non-trivial
31-
\* serializability test:
32-
\* - t1 reads {m1, m2}, writes {m1}. (conflicts with t2 on m1)
33-
\* - t2 reads {m1}, writes {m2}. (conflicts with t1 on m1,
34-
\* with t3 on m2)
35-
\* - t3 reads {m2}, writes {m3}. (conflicts with t2 on m2)
36-
\* Every pair of txns has an overlapping access-set, so 2PL must serialise
37-
\* *some* total order on them. TLC explores all possible commit orders.
29+
\* Scenario chosen: 3 transactions, 3 modalities, *partial* conflict graph.
30+
\* This is deliberately richer than the all-pairs-conflict case, which would
31+
\* trivially degenerate to a serial execution (at most 1 ACTIVE txn at any
32+
\* time, so serializability is free). Here:
33+
\* - t1 reads {m1}, writes {m1} -- disjoint from t2 (can run concurrently)
34+
\* - t2 reads {m2}, writes {m2} -- disjoint from t1 (can run concurrently)
35+
\* - t3 reads {m1, m2}, writes {m3} -- conflicts with BOTH t1 and t2
36+
\*
37+
\* Consequence: the reachable state graph contains states where t1 and t2
38+
\* are simultaneously ACTIVE (real concurrency), but t3 must serialise
39+
\* against each of them (real serialisation under 2PL). This scenario
40+
\* genuinely exercises `NoConcurrentConflict` rather than trivially
41+
\* satisfying it.
3842

3943
Txns == {"t1", "t2", "t3"}
4044
Modalities == {"m1", "m2", "m3"}
4145

4246
TxnReads == [t \in Txns |->
43-
CASE t = "t1" -> {"m1", "m2"}
44-
[] t = "t2" -> {"m1"}
45-
[] t = "t3" -> {"m2"}]
47+
CASE t = "t1" -> {"m1"}
48+
[] t = "t2" -> {"m2"}
49+
[] t = "t3" -> {"m1", "m2"}]
4650

4751
TxnWrites == [t \in Txns |->
4852
CASE t = "t1" -> {"m1"}

0 commit comments

Comments
 (0)