⬆️ ⬇️

Transaction Isolation Levels with PostgreSQL Examples

Introduction



The SQL standard describes four transaction isolation levels — Read uncommited, Read committed, Repeatable read, and Serializable. This article will look at the life cycle of four concurrently running transactions with Read committed and Serializable isolation levels.



For the Read committed isolation level, the following special data reading conditions are allowed:



Non-Repeatable Read — A transaction rereads the same data as before and finds that it was modified by another transaction (which ended after the first read).



Phantom read — A transaction re-executes a query that returns a rowset for a condition, and detects that the rowset that satisfies the condition has changed because of a transaction that has completed during this time.



As for Serializable, this isolation level is the strictest and has no data reading phenomena.



ACID or 4 transaction properties



Before we begin to consider the isolation levels of a transaction in a couple of words, we’ll recall the basic requirements for a transaction system.



Atomicity - is expressed in the fact that the transaction must be completed as a whole or not executed at all.



Consistency - ensures that as transactions are completed, data moves from one consistent state to another, that is, a transaction cannot destroy the mutual consistency of data.



Isolation - localization of user processes means that competing for access to the database transactions are physically processed sequentially, in isolation from each other, but for users it looks as if they are executed in parallel.



Durability - error tolerance - if a transaction is completed successfully, then the changes in the data that it has made cannot be lost under any circumstances.



Isolation level Read Committed



PostgreSQL's default isolation level is Read Committed. This isolation level always allows you to see the changes made by successfully completed transactions in the remaining open transactions in parallel. In a transaction running at this level, the SELECT query (without the FOR UPDATE / SHARE clause) sees only the data that was recorded before the query started; he will never see uncommitted data or changes made during the execution of a query by parallel transactions. Essentially, a SELECT query sees a snapshot of the database at the time the query starts. However, SELECT sees the results of changes made earlier in the same transaction, even if they are not yet fixed. Also note that two consecutive SELECT statements can see different data even within the same transaction if some other transactions commit changes after the first SELECT has been executed.



The essence of the Read Committed isolation level is shown in diagram 1.



Note: The table already contains an entry with the first version of the data (v1). Please take the command SELECT v1; - as a command that returns data versions v1, and UPDATE v1 to v2; - as a command to update data from the first version to the second.



We will create 4 connections to the database and open them in each of the transaction connections with the Read Committed isolation level.

Read Committed



Read Committed



Step 1. At the initial moment of time before any data changes, the initial version of the data (v1) is available to all transactions;

Read Committed



Step 2. During the operation of the First transaction, the data without any locks is successfully updated to the “second version” (v2);

Read Committed



Step 3. Changes made in the First transaction will be visible only to itself (SELECT returns v2), and will not be available to other transactions (SELECT query in the Second and Fourth transactions returns v1);

Read Committed



Step 4. Closing the First Transaction. All changes made during her work are successfully recorded;

Read Committed



Step 5. After closing the First transaction (previous step), changes made during its execution over the data (update from v1 to v2) were propagated to the remaining transactions, a SELECT query in the remaining 3 open transactions returns v2 (“Nonrepeatable reading”, distinguish the level isolation Read Committed from Serializable);

Read Committed



Step 6. The request to update the data in the Second transaction to the “third version” is successfully completed, but the requests to update the data block the rows to be modified to change them further, until the completion of the Second transaction;

Read Committed



Step 7. Due to the lock imposed on the data in the previous step, the Third transaction goes into standby mode with a request to delete the data. Waiting for the Third Transaction will occur until the closure of the Second Transaction;

Read Committed



Step 8. In spite of the fact that the Third Transaction is awaiting the closure of the Second, both the Second and Fourth transactions continue their work without any problems, returning data according to their versions. The second returns v3; the fourth returns v2;

Read Committed



Step 9. Closing the Second Transaction causes the data to be unlocked for modification. The isolation level Read Committed allows you to continue the work of the Third transaction without causing an error. Having access to change a new version of data (v3) The third transaction SUCCESSFULLY immediately “deletes” them (the difference Read Committed from Serializable);

Read Committed



Step 10. Before closing the Third transaction, the data will be deleted only within the Third transaction. The fourth transaction before closing the third data is available (SELECT query in the fourth transaction returns v3);

Read Committed



Step 11. Closing the Third Transaction. All changes made during her work are successfully recorded;

Read Committed



Step 12. The request for receiving data in the fourth transaction returns nothing (“Phantom read”, SELECT query returns 0 records).

Read Committed



Note. The diagram does not show the action of the INSERT query. Within this isolation level, the rows added, for example in step 3, in the First transaction, would be SEEED to the remaining transactions after the completion of the First transaction.



Partial transaction isolation, provided in Read Committed mode, is acceptable for many applications. This mode is quick and easy to use, but it is not suitable for all occasions. Applications that perform complex queries and changes may require a more strictly consistent presentation of data, such as Serializable.



Isolation level Serializable



The isolation level of Serializable provides unhindered access to the database of transactions with SELECT queries. But for transactions with UPDATE and DELETE requests, the isolation level Serializable does not allow modification of the same row within different transactions. When isolating such a level, all transactions are processed as if they are all running sequentially (one after another). If two simultaneous transactions try to update one and the same line, it will not be possible. In this case, PostgreSQL will force the transaction, the second, and all subsequent ones that tried to change the line to cancel (rollback - ROLLBACK).



The essence of the Serializable isolation level is shown in diagram 2.



Create 4 connections to the database and open in each of the connections under the transaction with the isolation level Serializable

Serializable



Serializable



Step 1. The initial version of the data is available to all transactions (v1);

Serializable



Step 2. During the operation of the First transaction, the data without any locks is successfully updated to the “second version” (v2);

Serializable



Step 3. Changes made in the First transaction will be visible only to itself (SELECT returns v2), and will not be available to other transactions (SELECT query in the Second and Fourth transactions returns v1);

Serializable



Step 4. A request to update the data in the first transaction (step 2), locks the updated rows, and puts into standby mode the second transaction with the request to delete the data. Blocking transactions on the updated data will occur before the closure of the First transaction;

Serializable



Step 5. In spite of the fact that the Second transaction is waiting for the closure of the First, both the Third and Fourth transactions continue their work without any problems, returning data according to their versions;

Serializable



Step 6. Completion of the First transaction removes blocking from the updated data, but within the limits of the Serializable isolation level, the repeated updating of data in parallel transactions is prohibited, and therefore an error occurs during the execution of the Second transaction (Serializable differs from Read Committed);

Serializable



Step 7. The SELECT query in the Second transaction becomes impossible, since the error that occurred in the previous step cancels (“blocks”) the transaction. The SELECT query in the Third and Fourth transactions returns the initial version of the data (v1). Although the first transaction was completed successfully, the changes were not visible to the rest of the open transactions (the difference between Serializable and Read Committed). Opening of the Fifth transaction in the upper left window;

Serializable



Step 8. Closing the Second Transaction. All changes made by this transaction will be canceled due to an error during its operation;

Serializable



Step 9. A SELECT query in the Fifth transaction returns the new version of the data (v2). The SELECT query in the Third and Fourth transactions returns the initial version of the data (v1);

Serializable



Step 10. The isolation level of Serializable still does not allow updating the data, the UPDATE request in the Third transaction is not completed successfully, with consequent consequences for the progress of the entire transaction (although the First transaction has already been successfully completed and all changes made to it are saved in the database ). But the UPDATE request in the Fifth transaction is completed successfully, since it is open after the completion of the First transaction, and works with the new version of the data;

Serializable



Step 11. Closing the Third Transaction. All changes made by this transaction will be canceled due to an error during its operation;

Serializable



Step 12. Transaction Four also shows that transactions with SELECT queries have no problems, and the Fifth transaction receives the same updated data (v5).

Serializable



Note. The diagram does not show the action of the INSERT query. Within this isolation level, the rows added, for example in step 3, in the First transaction, would be NOT AVAILABLE for the Second, Third and Fourth transactions after the completion of the First transaction. Also, the diagram does not show the result of ROLLBACK (Steps 8 and 11). If the Second and Third transactions made any changes to the unlocked data, then all these changes would not be recorded, since the transactions fail (the essence of the property is Atomicity).



The isolation level of Serializable ensures that all data affected by the transaction will not be altered by other transactions. At this level, the emergence of "phantoms" is excluded, therefore complex competitive operations become possible. In practice, this level of isolation is required in accounting systems.



For transactions containing only SELECT queries, the use of the Serializable isolation level is justified when you do not want to see the changes made in parallel with completed transactions during the course of the current transaction.



Serialization Anomaly (Lost Update)



Another phenomenon of reading data is described by the fact that the result of a successful fixation of a group of transactions is inconsistent with all sorts of options for executing these transactions in turn.



Orient me, please, in the comments, if I am mistaken about the fact that the anomaly of serialization and the lost update related phenomena.



The documentation on the PostgreSQL PRO website writes that Read Committed allows for “Serialization Anomaly” . Domestic Wikipedia, without insisting that the table refers specifically to PostgreSQL, writes that Read Commited prevents serialization anomaly . English Wikipedia about such a phenomenon of reading data is silent . But German Wikipedia cites the “Lost Updates” phenomenon in its version of the table, indicating that Read Committed may not be susceptible to the loss of updates with Cursor Stability. Ukrainian Wikipedia supports the Russian version of the article; Spanish Wikipedia supports the English version of the article. The English-language PostgreSQL documentation is no different from the documentation from the PostgreSQL PRO site.



Cursor Stability extends the blocking behavior of the READ COMMITED level for SQL cursors by adding a new read operation (Fetch) on the rc cursor (meaning read cursor, that is, reading on the cursor) and requiring the lock to be set on the current cursor element. The lock is held until the cursor is moved (until its current element is changed) or closed, possibly by a commit operation. Naturally, a transaction reading on the cursor can change the current line (wc is a record on the cursor), in which case the lock on the record of this line will be maintained until the transaction is committed, even after moving the cursor, followed by selecting the next line.


This is the result in PostgreSQL 9.6.

Serialization Anomaly, Lost Updates



Outcome: 149.



Conclusion



Understanding transaction isolation levels is an important aspect of data processing in any multi-user DBMS. Insulation levels have well-defined characteristics and behavior. Higher isolation levels reduce parallel processing and increase the risk of interlocking processes. Therefore, the correct use of levels depending on the tasks of the applications is always the choice of the developer depending on the requirements for ensuring the logical integrity of the data, speed and the possibility of parallel multi-user processing.



Literature



» MVCC Unmasked

" 13.2. Transaction isolation

» Criticism of isolation levels

» Transaction isolation levels in SQL. Crib

» Transaction Isolation Level

" ... the lost update phenomena



')

Source: https://habr.com/ru/post/317884/



All Articles