FV-7: MVCC write skew detection
- mvcc.tla: Add NoWriteSkew invariant - mvcc.tla: CommitTxn checks for circular read-write dependencies - models/mvcc.cfg: Add NoWriteSkew to checked invariants - Update PLAN.md, ANALYSIS.md, README.md
This commit is contained in:
@@ -96,9 +96,9 @@
|
||||
|
||||
- Version cleanup (стари версии се трият при compaction)
|
||||
- Long-running transaction handling (транзакции със стар snapshot)
|
||||
- Write skew detection (класически проблем на snapshot isolation)
|
||||
- ~~Write skew detection~~ ✅ Направено — `NoWriteSkew` инвариантата е добавена в `mvcc.tla`
|
||||
|
||||
**Препоръка:** Добавяне на `CleanupOldVersions` действие и `NoWriteSkew` инвариант (изисква tracking на predicate-based read/write конфликти).
|
||||
**Препоръка:** Добавяне на `CleanupOldVersions` действие.
|
||||
|
||||
### 2.7. Няма интеграция с Nim тестовете
|
||||
|
||||
|
||||
@@ -87,6 +87,7 @@ java -cp tla2tools.jar tlc2.TLC -config models/sharding.cfg sharding.tla
|
||||
- `WriteWriteConflict` — no two committed transactions write the same key (first-committer-wins).
|
||||
- `CommittedMustStart` — committed transactions have a valid start timestamp.
|
||||
- `CommittedVersionsUnique` — no two committed versions for a key share the same txnId.
|
||||
- `NoWriteSkew` — no two committed transactions have a circular read-write dependency.
|
||||
|
||||
### replication.tla
|
||||
- `MonotonicLsn` (temporal) — the applied LSN never decreases.
|
||||
|
||||
@@ -16,3 +16,4 @@ INVARIANTS
|
||||
WriteWriteConflict
|
||||
CommittedMustStart
|
||||
CommittedVersionsUnique
|
||||
NoWriteSkew
|
||||
|
||||
@@ -84,11 +84,16 @@ Write(t, k, v) ==
|
||||
/\ UNCHANGED <<txnState, txnStartTs, readSet, globalClock>>
|
||||
|
||||
\* Commit transaction t: mark its versions as committed (first-committer-wins).
|
||||
\* Also checks for write skew: if another committed txn read a key we wrote,
|
||||
\* and wrote a key we read, that's a circular dependency and we must abort.
|
||||
CommitTxn(t) ==
|
||||
/\ txnState[t] = "Active"
|
||||
/\ txnStartTs[t] > 0
|
||||
/\ ~(\E t2 \in 1..MaxTxnId : t2 /= t /\ txnState[t2] = "Committed" /\
|
||||
\E k \in Keys : k \in writeSet[t] /\ k \in writeSet[t2])
|
||||
/\ ~(\E t2 \in 1..MaxTxnId : t2 /= t /\ txnState[t2] = "Committed" /\
|
||||
\E k1 \in Keys : k1 \in writeSet[t] /\ k1 \in readSet[t2] /\
|
||||
\E k2 \in Keys : k2 \in writeSet[t2] /\ k2 \in readSet[t])
|
||||
/\ txnState' = [txnState EXCEPT ![t] = "Committed"]
|
||||
/\ db' = [k \in Keys |->
|
||||
IF k \in writeSet[t]
|
||||
@@ -142,6 +147,14 @@ WriteWriteConflict ==
|
||||
t1 /= t2 /\ txnState[t1] = "Committed" /\ txnState[t2] = "Committed" =>
|
||||
~(\E k \in Keys : k \in writeSet[t1] /\ k \in writeSet[t2])
|
||||
|
||||
\* No write skew: two committed transactions cannot have a circular read-write dependency.
|
||||
\* If t1 writes a key that t2 read, then t2 cannot write a key that t1 read.
|
||||
NoWriteSkew ==
|
||||
\A t1, t2 \in 1..MaxTxnId :
|
||||
t1 /= t2 /\ txnState[t1] = "Committed" /\ txnState[t2] = "Committed" =>
|
||||
~(\E k1 \in Keys : k1 \in writeSet[t1] /\ k1 \in readSet[t2] /\
|
||||
\E k2 \in Keys : k2 \in writeSet[t2] /\ k2 \in readSet[t1])
|
||||
|
||||
\* A committed transaction must have been started (has start timestamp > 0).
|
||||
CommittedMustStart ==
|
||||
\A t \in 1..MaxTxnId :
|
||||
|
||||
Reference in New Issue
Block a user