Transactions running at the same time
Isolation answers the question atomicity dodges. What happens when two transactions run at the same moment and touch the same data?
Perfect isolation means they behave as though they ran one after the other, in some order. Your database runs hundreds at once for throughput, so its job is producing that as-if-sequential result without actually queueing everything.
The anomalies are worth knowing by name, because they are what appears when isolation is too weak. A dirty read sees data from a transaction that has not committed and might still roll back. A non-repeatable read gets two different answers from the same row, because somebody committed in between. A phantom read runs the same query again and finds new rows.
Lost updates deserve special attention, since they are the quiet one. Two read-modify-write cycles interleave and one overwrites the other, so two support agents both open a ticket, both edit it, and the second save silently erases the first.
How the database pulls it off
The machinery in Postgres and MySQL is multi-version concurrency control. Writers do not overwrite rows, they create new versions, and each transaction reads from a snapshot of what was committed when it started.
That gives you the headline property: readers never block writers and writers never block readers. Two of your writers aiming at the same row still queue on a lock, but the read-write collision that dominated older databases mostly disappeared.
Isolation is sold in grades, because full isolation is expensive. Each grade from Read Committed up to Serializable closes more anomalies in exchange for more locking or more aborted transactions, and the next chapter is about exactly that. For now keep the contract straight: atomicity protects you from crashes, isolation protects you from other transactions, and your database's default protects you from less than you assume.
Worked example
A concert ticketing app has 2 seats left for a show. Ravi and Jess both hit buy within the same 20 ms. Each request runs: SELECT seats_left, sees 2, checks 2 >= 1, then UPDATE seats_left = 1. Both pass the check, both write, and the counter that should read 0 reads 1. Over a big on-sale weekend the venue oversells 37 seats this way. The fix keeps the check and the decrement in one atomic, isolated statement: UPDATE shows SET seats_left = seats_left - 1 WHERE id = 7 AND seats_left >= 1, then inspect the affected-row count. Now the database serializes the two updates on the row lock; Ravi's succeeds, Jess's matches zero rows and she sees "sold out." No isolation level change needed, just letting the database do the read-modify-write as one operation.