PhantomRead

See isolation levels break, step by step

Isolation levels you can step through, not just read about.

Two transactions, a shared table, and a real MVCC engine. Pick each transaction's isolation level and step them through, action by action. Every read resolves against a real snapshot; every write appends a real version. The anomalies happen because the semantics produce them. Raise the level and they vanish on their own.

What Phantom Read shows you

Every relational database gives you a dial called the isolation level. Turn it down and concurrent transactions run faster but can corrupt each other's view of the data; turn it up and the database protects you at the cost of aborting more commits. Most tutorials teach this as a grid of "prevents X, allows Y" with no way to see the machinery underneath. Phantom Read runs that machinery in the browser: a small multi-version concurrency control (MVCC) engine that keeps a version chain per row, takes a snapshot when each transaction begins, and resolves every read with the same visibility rules Postgres uses.

Pick a scenario, set an isolation level for each of the two transactions, and step forward one action at a time. You watch the shared table, the version chain, and each transaction's snapshot change on every step, so the anomaly is something you observe rather than something a diagram asserts. Raise the level and replay the same script to see the anomaly disappear, or the database abort the losing commit to keep your data consistent.

Frequently asked questions

What is a database isolation level?
It is the guarantee a database makes about how much one transaction can see of another that is running at the same time. The SQL standard names four: Read Uncommitted, Read Committed, Repeatable Read, and Serializable. Phantom Read models the top three, the ones a real MVCC database like Postgres actually offers.
What is a phantom read?
It happens when a transaction runs the same range query twice and the second run returns a row that was not there before, because another transaction inserted and committed it in between. Repeatable Read stops it by freezing the reading transaction's snapshot at the moment it began, so the new row stays invisible.
Does Repeatable Read prevent write skew?
No, and that surprise is the reason this tool exists. Two transactions can each read a value, check an invariant, and write a different row. Both snapshots were valid on their own, both commit, and together they break the invariant. Only Serializable catches it, by detecting the read-write conflict at commit time and aborting one transaction.
Is this a real database?
No. It is a faithful simulation of the visibility and conflict-detection rules a real MVCC engine uses, written in plain JavaScript so it runs with no server and no install. The same engine code powers both the UI and the test suite, so what you see on screen is exactly what the tests assert.
Which isolation level should I use in production?
It depends on your workload, but the honest default is: use the highest level your database offers by default (often Read Committed), and reach for Serializable on the specific transactions that guard an invariant across more than one row. Phantom Read helps you feel where that line is by letting you break the invariant and then protect it.