Experiments on the four isolation levels of transactions

Four levels of operations for database experiments

Background introduction:

1. Four characteristics of transaction (ACID)

The four characteristics of transactions that have to be understood before understanding the transaction isolation level.

1. Atomicity

After the transaction starts, all operations are either done or not done. The transaction is an indivisible whole. When a transaction fails during execution, it will roll back to the state before the transaction started to ensure the integrity of the transaction. Similar to the physical explanation of atoms: it refers to the basic particles that are inseparable in chemical reactions, and atoms are indivisible in chemical reactions.

2. Consistency

After the transaction starts and ends, it can ensure the correctness of the database integrity constraints, that is, the integrity of the data. For example, in a classic transfer case, when A transfers money to B, we must ensure that A deducts the money and B will definitely receive the money. Personal understanding is similar to the conservation of energy in physics.

3. Isolation

Complete isolation between transactions. For example, A transfers money to a bank card to avoid excessive operations at the same time causing the loss of the account amount, so other operations on this card are not allowed before the transfer of A is completed.

4. Durability

The impact of the transaction on the data is permanent. The popular explanation is that after the transaction is completed, the operation of the data must be placed (persistent). Once the transaction is completed, it is irreversible. In the operation of the database, the transaction cannot be rolled back once it is completed.

In the modern Internet, in order to meet the needs of a large number of users to operate data at the same time, similar to Taobao on Double Eleven, modern databases generally have a concurrency mechanism, but any thing that achieves the same performance must sacrifice another performance. In order to achieve concurrency, It also often creates many problems, which are reflected in the database or the operating system.

Q: The problem:

1. Dirty read

Also called invalid data read. One transaction reads data that has not yet been committed by another transaction is called dirty read.

2: Repeatable reading

In the same transaction, the same data read multiple times is inconsistent.

3: Dirty read refers to a phenomenon that occurs when the transaction is not executed independently.

Transaction A reads several rows that match the search criteria. Transaction B modifies the result set of transaction A by inserting or deleting rows, and then submits it.

A: How to solve this problem?

For this reason, mysql's innodb engine has introduced different transaction isolation mechanisms to solve these problems.

image-20201025101808075

conduct experiment:

1: Build a table:

CREATE TABLE accout(
id INT NOT NULL,
personname VARCHAR (255) NOT NULL,
balance INT NOT NULL,
PRIMARY KEY (id)
)     

2: Insert data:

INSERT INTO accout 
VALUES(1,"alice" ,1000),
			(2, "bob", 900),
			(3, "jack", 800),
			(4, "Amy" , 700),
			(5,"Andy", 600)

Table at this time:

set session transaction isolation level read ;
START TRANSACTION;
UPDATE accout SET balance = balance + 100; image-20201025102955906

Set the isolation level read uncommitted

 set session transaction isolation level read uncommitted;

Start two transactions: session 1 and session 2

Among them: session 2:

set session transaction isolation level readSTART TRANSACTION;
UPDATE accout SET balance = balance + 100;

Execute, and the query result in session 1 is:

select * from accout;

result:

image-20201025103938026

For some reason, session 2 is rolled back, and session 1 is reduced by 100

ROLLBACK;
COMMIT;
UPDATE accout set balance = balance -100;
commit;
selet * from accout;

result:

image-20201025105123520

We will find that it is 100 yuan more inexplicably, why?

This is because when session1 starts to add 100 yuan, session1 feels that the query result is the correct data.

We found that the final data was inconsistent due to dirty read session1. The correct result should be Andy 500; at
this point, how do we avoid dirty reads? Increase the isolation of transactions by one level to read-commit

read-commit solves dirty reads

Set the transaction isolation level,

 set session transaction isolation level read committed;

Repeat the above operation:

session 2

image-20201025105809989

Data queried in session1:

image-20201025105701481

We found that the transaction isolation was upgraded to read-committed; after the two transactions were effectively isolated, the transaction in session1 could not query the data changes made by the transaction in session2. Effectively avoid dirty read

Then proceed:

The result matchesimage-20201025110210365

Non-repeatable read of read-commit

Reset the data to restore the data to its original state

Open the transaction:

start transaction;

Session1 first query:

image-20201025111336800

session 2 is updated,

 set session transaction isolation level read committed;
 START TRANSACTION;

UPDATE accout SET balance = balance - 100;
SELECT * FROM accout;


Inquired again for session 1 and found the same, because session 2 did not commit.

image-20201025111336800

But after commit, the query result is as follows

image-20201025123923495

Looking at the query results, we can see that the repeated read results of session1 are inconsistent during the open transaction

A non-repeatable read occurred.

repeatable-read

Restore data, set the isolation level to repeatable-read


set session transaction isolation level repeatable read;

Repeat the above operation, the second query of session1 is

image-20201025124518022

It doesn't seem to have changed, let's explore how this ensures that the two transactions do not affect each other.

We also do it in session1

UPDATE accout SET balance = balance +100;

It was found that it could not be carried out. It turned out to be a lock mechanism. Session1 can only run after session2 commits.

image-20201025125446817

-repeatable-read phantom reading

1: Both transactions are running:

 set session transaction isolation level repeatable read;
 start transaction;
 select * from  accout;

Take a snapshot

image-20201025125846522

2 :session 2

INSERT INTO accout values(6,"wen" , 50);
commit;

image-20201025130056834

3::: Query in session 1 and find that the result is

image-20201025130223394

At this time, according to our usual business logic, the data with id=6 should be successfully inserted at this time

INSERT INTO accout values(6,"wen" , 50);

image-20201025130414386

, The result fails to insert, indicating that the item already exists, but there is no data in our query. Why does the insertion fail?

Because the select statement in ① generates a snapshot, subsequent read operations (without read lock) are all snapshot reads, that is, before the end of the current transaction, the results of all read operations are the snapshots generated by the first snapshot read version. The question comes again, why is the select statement in step ② not the snapshot version? Because the update statement will update the snapshot version of the current transaction

So how to solve it?

Use the current reading method

 select * from tb_bank lock in share mode;//采用当前读

image-20201025130821636

This solves the snapshot problem.

Serializable:

When the SERIALIZABLE-serializable isolation level is used,
other threads can only wait until the current operation is completed before performing the operation before the transaction is submitted . This is very time-consuming and affects the performance of the database. Usually Case, this isolation level will not be used

At the expense of performance, the thread can only be executed by the current before proceeding to the next problem.

Guess you like

Origin blog.csdn.net/weixin_43843172/article/details/109276577