Basic context behind the jargon:
* shared data — in memory or disk
* at least 2 threads. Isolation between threads.
0) concurrent, interleaved writes — no transaction. no isolation. 2 threads can each update half of a row’s data, corrupting it. I don’t think any DB allows this.
1) dirty read or “read uncommitted”(RU) — Easy. when a reader thread/session gets to see another thread’s uncommitted data change, that’s one count of read-uncommitted offense. We say this system “allows read-uncommitted“. This is the lowest isolation level, but higher than (0) above.
2) read committed (RC)  — If system doesn’t expose uncommitted data change, then read-uncommitted will never occur. If system is configured this way, then /each thread only reads committed changes/. However, each thread doesn’t get repeatable-read-by-id guarantee.
3) repeatable read (RR) by id — Your thread reads an item by id and writes something /based/ on the read. If you can reliably read, read, read for a long time … to get the *same* data before your write, then you are lucky  — no other session is allowed to touch that object. You get Repeatable Read on that object guarantee by the system. This system is operating in the RR mode.
Basically, system locks all rows of your first read and reserves them for you — pessimistic locking.  Once you read a row, it’s reserved for you. You are an emperor — once you cast your eyes on a girl, you have the right on her.
4) phantom read — However, if you read with a range-select like “where price > 0”, then your first read can reserve 500 rows and a repeated read can turn up 501 rows. This is a count of Phantom Read. I feel this query is not repeatable. It’s not a read-by-id, so RR is not relevant.
Solution for phantom read is — a range-lock rather than a row or page lock. Some say “serialize all threads that access a given range”.
Say Transaction1 has just finished a read with “from table1 where age > 22”, uncommitted. Can system allow Transaction2 to start, one that doesn’t mention this table? If system lets Transaction2 start, Transaction2 may lock up another table. Since Transaction1 locks up table1, there’s risk of deadlock. It’s safest to serialize all transactions.
 but not necessarily on that query
 luckier than the threads in a RC system
 RC is the default in most databases.
 Now the “system” could be a table or a database or a multi-threading app. There’s absolutely(?) no control, coordination, discipline or “isolation” in this RU mode. Isolation is the I in ACID.
 Now we know every SELECT is implicitly in a new transaction. In RR mode, it locks up all the rows involved until commit. This is more strict than the default RC mode.