A lost update in four steps
This is a real run of the banking example, recorded with seed 42. Nothing on this page is mocked.
Two withdrawals read the same balance
Both transactions read $1,000 before either one writes. Each is correct on its own.
Each one writes its own result
The first debits $19 and saves $981. The second debits $11 and saves $989.
The second write erases the first
The account ends at $989 instead of $970. A $19 debit vanished and no error reaches the logs.
ChaosSQL proves it and hands you the test
The invariant fails, the engine replays the exact order, and delta debugging keeps only the 2 transactions that cause it, in repro_test.go.
- T1: BEGIN
- T2: BEGIN
- T1: SELECT balance FROM accounts WHERE id = 1;
- T2: SELECT balance FROM accounts WHERE id = 1;
- Stored balance
- $1,000
- Expected
- $970
- Invariant
- checked when both commit
repro_test.go20 to 2 transactions
Words used here
- Invariant
- A rule your data must always obey, written as a SQL query. For example: the balance equals the opening balance minus every debit.
- Isolation level
- How much one transaction can see of another that is still running. Weaker levels are faster and allow more of these bugs.
- Seed
- A number that fixes the order of every operation, so the same seed replays the same run.
