As if they ran one at a time
Serializable is the top rung. The database guarantees the outcome of your concurrent transactions matches some serial ordering of them, so every anomaly on the list becomes impossible, write skew and phantoms included.
Your reasoning collapses to one question: would this be correct if transactions ran one at a time? That is the only question most people can answer reliably.
What it costs, and where
How your database implements it matters, because the price depends on that. Traditional locking takes range locks on everything you read and holds them until commit. That is correct, and it makes readers and writers block each other until the rate of work sinks.
Postgres takes a different route. Transactions run optimistically on snapshots while the engine watches the dependencies between them, and it aborts one whenever a pattern appears that could produce a non-serializable result. Nothing blocks, and transactions fail with a serialization error your application must retry.
That overhead is modest when contention is low and brutal on a hot row everybody fights over. CockroachDB runs serializable as its only level, which tells you the cost is payable when the engine is designed around it.
Spend it deliberately, because levels are set per transaction and not per database. Keep Read Committed as the default. Apply Serializable to the handful of transactions holding invariants that span rows: balancing a ledger, seat inventory, the on-call rule from the previous lesson, and uniqueness rules too complex for an index.
Wrap them in a retry helper with a capped number of attempts and a little randomness, keep them short so the conflict window stays small, and watch the abort rate. A climbing count of serialization failures is your early warning that contention is growing.
Worked example
A brokerage app enforces that a customer's positions never exceed their margin limit, a rule spanning the positions and collateral tables. At Repeatable Read, two simultaneous orders from customer Chen each check the limit against the same snapshot, each pass individually, and together push him 8,000 dollars over. Compliance notices within a week. The team moves order placement, and only order placement, to Serializable. Under load testing at 400 orders per second, about 1.5 percent of transactions abort with serialization errors; a retry wrapper with three attempts and 10 ms jittered backoff absorbs nearly all, adding under 15 ms at p99, the figure 99 requests in every 100 come in under. Everything else in the app stays at Read Committed and unaffected. Chen's racing orders now serialize: the second one recomputes against the first one's committed result and is correctly rejected.