362

I think the above isolation levels are so alike. Could someone please describe with some nice examples what the main difference is?

Sire
  • 4,086
  • 4
  • 39
  • 74
Fore
  • 5,726
  • 7
  • 22
  • 35
  • 4
    You should expand on the question and add tags for what "isolation level" you're referring to (Java, etc). "isolation level" is a somewhat ambiguous term, and you're obviously asking for an answer for a specific environment. – jesup Oct 27 '10 at 15:39

9 Answers9

791

Read committed is an isolation level that guarantees that any data read was committed at the moment is read. It simply restricts the reader from seeing any intermediate, uncommitted, 'dirty' read. It makes no promise whatsoever that if the transaction re-issues the read, will find the Same data, data is free to change after it was read.

Repeatable read is a higher isolation level, that in addition to the guarantees of the read committed level, it also guarantees that any data read cannot change, if the transaction reads the same data again, it will find the previously read data in place, unchanged, and available to read.

The next isolation level, serializable, makes an even stronger guarantee: in addition to everything repeatable read guarantees, it also guarantees that no new data can be seen by a subsequent read.

Say you have a table T with a column C with one row in it, say it has the value '1'. And consider you have a simple task like the following:

BEGIN TRANSACTION;
SELECT * FROM T;
WAITFOR DELAY '00:01:00'
SELECT * FROM T;
COMMIT;

That is a simple task that issue two reads from table T, with a delay of 1 minute between them.

  • under READ COMMITTED, the second SELECT may return any data. A concurrent transaction may update the record, delete it, insert new records. The second select will always see the new data.
  • under REPEATABLE READ the second SELECT is guaranteed to display at least the rows that were returned from the first SELECT unchanged. New rows may be added by a concurrent transaction in that one minute, but the existing rows cannot be deleted nor changed.
  • under SERIALIZABLE reads the second select is guaranteed to see exactly the same rows as the first. No row can change, nor deleted, nor new rows could be inserted by a concurrent transaction.

If you follow the logic above you can quickly realize that SERIALIZABLE transactions, while they may make life easy for you, are always completely blocking every possible concurrent operation, since they require that nobody can modify, delete nor insert any row. The default transaction isolation level of the .Net System.Transactions scope is serializable, and this usually explains the abysmal performance that results.

And finally, there is also the SNAPSHOT isolation level. SNAPSHOT isolation level makes the same guarantees as serializable, but not by requiring that no concurrent transaction can modify the data. Instead, it forces every reader to see its own version of the world (its own 'snapshot'). This makes it very easy to program against as well as very scalable as it does not block concurrent updates. However, that benefit comes with a price: extra server resource consumption.

Supplemental reads:

danronmoon
  • 3,814
  • 5
  • 34
  • 56
Remus Rusanu
  • 288,378
  • 40
  • 442
  • 569
  • 41
    I think there is a mistake above for REPEATABLE READ: You say existing rows cannot be deleted nor changed, but I think they can be deleted or changed because repeatable read simply reads a "snapshot" not the actual data. From the docs http://dev.mysql.com/doc/refman/5.0/en/set-transaction.html#isolevel_repeatable-read: "All consistent reads within the same transaction read the snapshot established by the first read." – Derek Litz Jan 17 '13 at 16:40
  • 3
    @Derek Litz Am I right in that you are saying: The data CAN/MAY be changed from a third party, whilst the transaction is taking place, but the reads will still see the 'old' original data as if the change had not taken place (the snapshot). – Programster Nov 08 '13 at 17:04
  • I take it that with all these isolation levels (except dirty, which may be why someone wants to use it), performing a read/write/read wont result in the second read being different from the first only because of the write this transaction is performing mid way through. – Programster Nov 08 '13 at 17:07
  • @Stu2000 Yeah, when doing adhoc testing after switching from SQLServer to MySQL which have different isolation levels I got brained a couple times by old data coming back from a old transaction. – Derek Litz Nov 11 '13 at 00:17
  • This is slightly incorrect. Data may be deleted under REPEATABLE READ. REPEATABLE READ just requires that the data in the rows do not change; which rows are returned by a query may be changed (i.e. insertions/deletions will be seen, but not updates). This is the whole idea behind phantom reads. Rows might be phantoms (they may appear/disappear), but the data contained in them won't change. – Cornstalks Apr 30 '14 at 16:29
  • 1
    @Cornstalks, this is not correct. Data may be inserted amongst the selected range, leading to phantom reads, but it may NOT be updated **OR deleted**. [This Blog](http://blogs.msdn.com/b/craigfr/archive/2007/05/09/repeatable-read-isolation-level.aspx) explains it well, or you can test it for yourself. – AndyBrown Sep 19 '14 at 11:03
  • @AndyBrown: No, I'm right. [Read this MSDN documentation about phantom reads](http://technet.microsoft.com/en-us/library/ms190805(v=sql.105).aspx) (it explicitly says *insert* and *delete*). [Then confer this MSDN documentation that explicitly says phantom reads are allowed for repeatable read](http://technet.microsoft.com/en-us/library/ms189122(v=sql.105).aspx). – Cornstalks Sep 19 '14 at 14:31
  • 2
    @Cornstalk: Is really *trivial* to test you assumption. Set tran isolation repeatable read, begin tran, read rows, don't commit. From second session try to delete the rows read. Let us know the result. – Remus Rusanu Sep 19 '14 at 14:57
  • 6
    @Cornstalks. Yes, Phantom reads can occur from deletes (or inserts). Yes, phantom reads can occur in repeatable read isolation (from inserts only). No, Phantom reads from deletes cannot occur in repeatable read isolation. Test it. What I am saying is not contradicted by the documentation you have quoted. – AndyBrown Sep 19 '14 at 15:00
  • @RemusRusanu: I tried to get phantom reads (from inserts and deletes) with MySQL, but couldn't get anything with my trivial tests. Perhaps I was testing wrong. But Andy has helped me understand where my logic was faulty. – Cornstalks Sep 19 '14 at 15:18
  • 3
    @AndyBrown (and Remus Rusanu): I'm willing to delete my original comment (to avoid misleading future readers), but I'm also willing to leave it (to preserve the context of these comments). I'll leave it, but if you think it would be best to delete it I will. – Cornstalks Sep 19 '14 at 15:21
  • 7
    @Cornstalks NP. I only mentioned it at all because I wasn't 100% sure myself and had to deep-dive to be sure who was right! And I didn't want future readers to be mislead. Re keeping the comments, probably best to keep as suggested. I'm sure anyone else interested in that level of fine detail will be particular enough to read all the comments!! – AndyBrown Sep 19 '14 at 15:35
  • 1
    There is some discrepancy amongst the current comment thread. @DerekLitz was correct as per the MySQL 5.7 documentation on consistent reads which READ COMMITTED and REPEATABLE READ isolation levels use. Straight from the docs, "consistent read does not set any locks on the tables it accesses, other sessions are free to modify those tables while a consistent read is being performed on the table." – roflmyeggo Apr 16 '18 at 20:09
  • @RemusRusanu Under serializable, if the second select was applied to a different table than `T` (let's call it `T2`) that was modified during the transaction, will the second select retrieve the new values or those that were the moment the transaction started? – Mehdi Charife May 08 '23 at 15:27
91

Repeatable Read

The state of the database is maintained from the start of the transaction. If you retrieve a value in session1, then update that value in session2, retrieving it again in session1 will return the same results. Reads are repeatable.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Aaron

Read Committed

Within the context of a transaction, you will always retrieve the most recently committed value. If you retrieve a value in session1, update it in session2, then retrieve it in session1again, you will get the value as modified in session2. It reads the last committed row.

session1> BEGIN;
session1> SELECT firstname FROM names WHERE id = 7;
Aaron

session2> BEGIN;
session2> SELECT firstname FROM names WHERE id = 7;
Aaron
session2> UPDATE names SET firstname = 'Bob' WHERE id = 7;
session2> SELECT firstname FROM names WHERE id = 7;
Bob
session2> COMMIT;

session1> SELECT firstname FROM names WHERE id = 7;
Bob

Makes sense?

BenMorel
  • 34,448
  • 50
  • 182
  • 322
Hazel_arun
  • 1,721
  • 2
  • 13
  • 17
  • I tried Repeatable Read in SQL Server 2008 with "set isolation level repeatable read". Created two sql query windows. But did not work. Why? – Aditya Bokade Aug 17 '13 at 01:57
  • 1
    Why would the second session1 still read out Aaron? Isn't session2's transaction finished and commited? I know this old, but maybe someone can shed some light. – Sonny Childs May 20 '15 at 12:27
  • 19
    I think the Repeatable Read will block the second session until the first session committed. So the example is wrong. – Nighon Jul 22 '16 at 09:22
  • 5
    In case of Repeatable Read, when session 1 reads the row, it puts a shared lock, which would not allow any Exclusive lock (to session 2) for update, hence the data cannot be updated. – Taher Mar 20 '17 at 16:58
  • 2
    I think SQL server and MySQL behave differently when it comes to update of shared rows between two transactions – user2488286 Jun 28 '19 at 06:46
76

Simply the answer according to my reading and understanding to this thread and @remus-rusanu answer is based on this simple scenario:

There are two transactions A and B. They perform the following operations in this following sequence.

  • Transaction B is first reads from Table X
  • Transaction A then writes to table X
  • Transaction B then readings again from Table X.
  • ReadUncommitted: Transaction B can read uncommitted data from Transaction A and it could see different rows based on A writing. No lock at all
  • ReadCommitted: Transaction B can read ONLY committed data from Transaction A and it could see different rows based on COMMITTED only A writing. could we call it Simple Lock?
  • RepeatableRead: Transaction B will read the same data (rows) whatever Transaction A is doing. But Transaction A can change other rows. Rows level Block
  • Serialisable: Transaction B will read the same rows as before and Transaction A cannot read or write in the table. Table-level Block
  • Snapshot: every Transaction has its own copy and they are working on it. Each one has its own view
FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
Mo Zaatar
  • 925
  • 8
  • 12
  • 1
    Very concise and to the point. I would replace the word 'Process' by 'transaction' – Junaed Aug 27 '20 at 10:21
  • @Mo Zaatar when should we use `table level block`? I think `Rows level Block` seems enough for all the use cases. – meallhour Oct 19 '22 at 19:43
  • There are some problems with this answer as it stands as there are some inconsistencies. I have made a small edit to the answer to make it clearer, however there are some outstanding issues. Before I address those, if my edits have made the answer worse in some way please explain to me why. – FreelanceConsultant Mar 31 '23 at 12:41
  • To address issues: Read Committed. "Could we call it a simple lock?" - Why? There is no locking here as far as I can tell. – FreelanceConsultant Mar 31 '23 at 12:41
  • RepeatableRead: The answer states "Transaction A can change..." is inconsistent with "Row level block". These two things cannot be true simultaniously. If there is a row level block in place then by definition Transaction A cannot change the data. – FreelanceConsultant Mar 31 '23 at 12:42
  • Which DBMS supports Snapshot? I'm not aware of Oracle supporting this and I don't think MariaDB does either. If it does, then DBeaver doesn't support it. – FreelanceConsultant Mar 31 '23 at 12:43
29

Old question which has an accepted answer already, but I like to think of these two isolation levels in terms of how they change the locking behavior in SQL Server. This might be helpful for those who are debugging deadlocks like I was.

READ COMMITTED (default)

Shared locks are taken in the SELECT and then released when the SELECT statement completes. This is how the system can guarantee that there are no dirty reads of uncommitted data. Other transactions can still change the underlying rows after your SELECT completes and before your transaction completes.

REPEATABLE READ

Shared locks are taken in the SELECT and then released only after the transaction completes. This is how the system can guarantee that the values you read will not change during the transaction (because they remain locked until the transaction finishes).

Chris Gillum
  • 14,526
  • 5
  • 48
  • 61
  • Doesn't this suggest that Repeatable Read is the same as Serializable? Regardless good answer. – FreelanceConsultant Mar 31 '23 at 12:44
  • @FreelanceConsultant from a locking perspective they are pretty similar. However, there are some other differences discussed here https://stackoverflow.com/q/13374335/2069. The ability to have phantom reads is one example mentioned when using repeatable read vs serializable. – Chris Gillum Apr 01 '23 at 00:08
  • Yes, and your answer suggests that phantom reads are not possible in "Repeatable Read" which is not true. – FreelanceConsultant Apr 01 '23 at 11:43
21

Trying to explain this doubt with simple diagrams.

Read Committed: Here in this isolation level, Transaction T1 will be reading the updated value of the X committed by Transaction T2.

Read Committed

Repeatable Read: In this isolation level, Transaction T1 will not consider the changes committed by the Transaction T2.

enter image description here

Community
  • 1
  • 1
vkrishna17
  • 906
  • 10
  • 17
6

I think this picture can also be useful, it helps me as a reference when I want to quickly remember the differences between isolation levels (thanks to kudvenkat on youtube)

enter image description here

ivpavici
  • 1,117
  • 2
  • 19
  • 30
2

There are other answers here, but they don't give any details about the underlying database architecture, which makes it difficult to understand why the transaction isolation levels function the way they do, and what problems are solved.


General Overview of Common Problems in Concurrent Environments

Database systems permit multiple concurrent connections. This leads to the same kinds of problems seen in other concurrent systems. For example, in multithreaded environments, mutexes prevent concurrent access to memory, thus solving the problem of race conditions which can lead to corrupt or invalid data.

In a similar way, because database systems permit concurrent CRUD operations (update, insert, delete, select), concurrent operations by multiple connections can lead to undesirable observed behaviour.

Note that the atomicity of database row operations prevents outright data corruption or inconsistency, so there is always a base level of transaction isolation enforced at all times.

For more information on this, see ACID. (Atomic, Consistent, Isolation, Durability.) The short explanation is that on a per-row basis, operations are atomic. This means prevents data corruption by preventing a situation whereby one connection would write part of a rows data, before another connection corrupted that data by partially writing its data to the same row. (This will be more intuitive to those familiar with multithreaded environments.)

The above described problem is analagous to problem seen in multithreaded programming whereby one thread begins writing to a block of memory, and then another thread comes and partially writes its data to the same block, before the first thread is finished. This results in inconsistent data.

It is important to understand the atomic nature of row operations first, because this already provides a base level of protection.

Types of Transaction Isolation Levels

We will look at the following Transaction Isolation levels, whcih are available in MariaDB and many other SQL database implementations.

We first need to know what the different isolation levels are:

  • Read uncommitted
  • Read committed
  • Repeatable read
  • Serializable

What problems are solved by the Transaction Isolation Levels?

Before explaining what these different options do, it is important to understand the problems solved by each of them. Here is a list of potential unwanted behaviours.

  • Dirty read
  • Non-repeatable read
  • Phantom read
Dirty Read:

Database operations are often grouped together into a transaction. This transaction is then either committed to the database as a group of operations, or a rollback is perfomed to discard the group of operations.

If one Connection starts a series of operations as a transaction, and then a second Connection begins reading data from the same table(s), the second Connection could either read the data from the database which has been committed, or it could also read the changes made as part of the open, and yet uncommitted, transaction.

This defines the difference between read committed and read uncommitted.

This is conceptually unusual, because it often doesn't make much sense to read uncommitted data. The whole point of transactions is to ensure data in the database does not change in this way.

To summarize:

  • Connection A opens a transaction and begins queueing up modifying (write) operations
  • Connection B opens in read-uncommitted mode, and reads data from the database
  • Connection A continues queueing up further modifications
  • If Connection B reads the data again, it will have changed
  • If Connection A performs a rollback, and then Connection B performs another read, the data read will have changed due to the rollback of the uncommitted data
  • This is known as a dirty read
  • This isn't a situation you usually have to worry about because you probably shouldn't be working in read-uncommitted mode as a general rule because it makes data appear as if transactions didn't exist, which is weird
Non-Repeatable Read

Given the above, a Non-Repeatable read may occur if the read operation mode is set to "Read Committed". This mode solves the problem of Dirty Read because only committed data is read.

The possible write operations are:

  • update
  • insert
  • delete

A Non-Repeatable Read occurs when a read operation reads a set of rows, and then the operation is repeated and the same set of rows (same keys) are returned, but the non-key data has changed.

For example:

  • Connection A may read a set of rows from a table. These rows are selected based on some selection criteria, for example a where clause.
  • Connection B may alter one or more of the rows in this set, as well as others
  • If Connection A repeats the same read query, then the same set of rows will be returned, but data which is not part of the "key" may have changed.
  • The "key" is defined by the selection criteria in the where, or other filter, clause.
Phantom Reads

Phantom Reads are an extension of the Non-Repeatable read. An insert or delete operation may change the rows returned in the set of returned rows. An insert operation may add new rows to the set of returned rows. A delete operation may do the opposite and remove rows from the set of returned rows.

To summarize:

  • Connection A perfoms a read operation
  • Connection B performs an insert, or delete, operation
  • Connection A performs the same read operation resulting in a different set of rows being returned. New rows may appear. Existing rows may dissappear. Hence "Phantom" Read.

Isolation Levels

Given our understanding of the potential undesirable behaviours, this is what the isolation levels do:

  • Read uncommitted does nothing to prevent any of these problems. However there is still a base level of protection due to atomic row operations.
  • Read committed prevents Dirty Reads only.
  • Repeatable Read prevents Dirty and Non-Repeatable Reads, but not Phantom Reads.
  • Serializable prevents all of the above.

Higher levels of isolation require more data in the database to be "locked" preventing concurrent access. This can be undesirable, because if a DMBS is holding a lock over a whole table, then no other connections can modify that data. This might cause other processes which need access to the database to hang.

Read Committed is typically the most sensible choice. It ensures that you, the Database Administrator, see only the committed data (data which is persistent, not transient) and it will not cause other processes to hang.

Bibliography

Further reading:

Wikipedia ACID Operations

Isolation Levels in MariaDB

Geeks for Geeks Isolation Levels. (Be aware some of the information doesn't make any sense, for example the explanation of Read Committed, which states that this causes a commit of any uncommitted data which is read. That is not correct and does not make sense. Uncommitted data is only committed by an explicit commit operation.)

Non-Repeatable Read vs Phantom Read

FreelanceConsultant
  • 13,167
  • 27
  • 115
  • 225
1

Please note that, the repeatable in repeatable read regards to a tuple, but not to the entire table. In ANSC isolation levels, phantom read anomaly can occur, which means read a table with the same where clause twice may return different return different result sets. Literally, it's not repeatable.

-1

My observation on initial accepted solution.

Under RR (default mysql) - If a tx is open and a SELECT has been fired, another tx can NOT delete any row belonging to previous READ result set until previous tx is committed (in fact delete statement in the new tx will just hang), however the next tx can delete all rows from the table without any trouble. Btw, a next READ in previous tx will still see the old data until it is committed.

Sanjeev Dhiman
  • 1,169
  • 1
  • 11
  • 20
  • 2
    You might want to put it in the comments section for the answerer to get notified. That way he will be able to respond to your observations and make corrections if required. – RBT Aug 24 '16 at 10:03