[MySQL] Transactions and their isolation/isolation levels


Students who need cloud servers and other cloud products to learn Linux can move to / --> Tencent Cloud <-- / --> Alibaba Cloud <-- / --> Huawei Cloud <-- / official website, lightweight cloud servers are low-cost to 112 yuan/year, and new users can enjoy ultra-low discounts on their first order.


 Table of contents

1. The concept of affairs

1. Four characteristics of transactions

2. The role of affairs

3. Storage engine support for transactions

4. Transaction submission method

2. Transaction startup, rollback and submission

1. Preparation: Adjust the default isolation level of MySQL to the lowest/Create a test table

2. Transaction startup, rollback and submission

3. If the transaction is not committed after starting the transaction, but the client crashes, MySQL will automatically roll back

3. Transaction isolation level

1. Isolation

2. Isolation level

3. Isolation viewing and setting

3.1 Isolated viewing

3.2 Set isolation level

4. Detailed explanation of the four isolation levels

4.1Read Uncommitted【Read Uncommitted】

4.2 Read Committed

4.3 Repeatable Read【Repeatable Read】

4.4 Serialization [Serializable]


1. The concept of affairs

1. Four characteristics of transactions

A transaction is composed of a group of DML statements. These statements are logically related. This group of DML statements either all succeed or all fail. It is a whole. For example, a bank transfer operation appears to be a simple transfer operation from the upper layer, but the lower layer requires one or more SQL statements to complete the transfer operation. This set of SQL statements is a whole and is called a transaction. The transaction also stipulates that the data seen by different clients is different.

A MySQL database can have more than one transaction running. At the same time, a large number of requests are packaged into transactions and initiate transaction processing requests to the MySQL server. If multiple users access the same table data without protection, problems will definitely occur. Moreover, the transaction consists of multiple SQL statements, and there may be situations where an error occurs in the middle of execution or the transaction does not want to be executed again. So what should I do if it has already been executed?

Therefore, a complete transaction is definitely not a simple SQL collection. It also needs to satisfy the following four attributes:

Atomicity: All operations in a transaction are either completely completed or not completed, and will not end somewhere in the middle. If an error occurs during the execution of the transaction, it will be rolled back to the state before the transaction started, as if the transaction had never been executed.

Consistency: The integrity of the database is not compromised before the transaction begins and after the transaction ends. This means that the data written must fully comply with all preset rules, including the accuracy and concatenation of the data, and that the subsequent database can spontaneously complete the predetermined work. Atomicity, isolation, and durability are causes, and consistency is the effect.

Isolation: The database allows multiple concurrent transactions to read, write and modify its data at the same time. Isolation can prevent data inconsistency due to cross execution when multiple transactions are executed concurrently. Transaction isolation is divided into different levels, including read uncommitted (Read uncommitted), read committed (read committed), repeatable read (repeatable read) and serialization (Serializable)

Durability: After the transaction is completed, the modifications to the data are permanent and will not be lost even if the system fails.

The above four attributes can be referred to as ACID.

Atomicity ( or indivisibility )

Consistency _ _

Isolation ( also known as independence)

Durability . _

2. The role of affairs

When programmers write upper-level code logic to access the database, transactions can simplify various details that need to be considered during programming. For example, when we use transactions, we can either commit or rollback, and we don't have to worry about network abnormalities, server downtime, etc.

3. Storage engine support for transactions

In MySQL, only Innodb supports transactions, while MyISAM does not.

4. Transaction submission method

Transaction submission methods are divided into automatic submission and manual submission.

Automatic submission:

--查看MySQL事务的提交方式发现是自动提交
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.02 sec)

Use set to change MySQL's transaction submission method: 

--将MySQL的事务提交方式修改为禁止自动提交
mysql> set autocommit=0;
Query OK, 0 rows affected (0.01 sec)

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | OFF   |
+---------------+-------+
1 row in set (0.00 sec)

--将MySQL的事务提交方式修改为开启自动提交
mysql> set autocommit=1;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.00 sec)

2. Transaction startup, rollback and submission

1. Preparation: Adjust the default isolation level of MySQL to the lowest/Create a test table

In order to see the demonstration phenomenon, first set the default isolation level of MySQL to read uncommitted (the lowest) and then exit and restart:

mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.00 sec)
--修改默认隔离级别生效
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)

Create test table:

create table if not exists account(
id int primary key,
name varchar(50) not null default '',
blance decimal(10,2) not null default 0.0
)ENGINE=InnoDB DEFAULT CHARSET=UTF8;

2. Transaction startup, rollback and submission

User: jly

--1、查看当前MySQL在线用户
mysql> show processlist;--开始一个事务也可以用begin
+-----+------+-----------+------------------+---------+------+----------+------------------+
| Id  | User | Host      | db               | Command | Time | State    | Info             |
+-----+------+-----------+------------------+---------+------+----------+------------------+
| 474 | jly  | localhost | transaction_data | Query   |    0 | starting | show processlist |
| 475 | jly  | localhost | NULL             | Sleep   |  132 |          | NULL             |
| 476 | root | localhost | NULL             | Sleep   |    5 |          | NULL             |
+-----+------+-----------+------------------+---------+------+----------+------------------+
3 rows in set (0.00 sec)
--2、先确认事务的提交方式为自动提交
mysql> show variables like 'autocommit';
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| autocommit    | ON    |
+---------------+-------+
1 row in set (0.02 sec)
--3、开始一个事务,start transaction执行之后,后方的SQL将处于同一个事务
mysql> start transaction;
Query OK, 0 rows affected (0.00 sec)
--4、创建一个保存节点save1
mysql> savepoint save1;
Query OK, 0 rows affected (0.00 sec)
--5、在当前表中插入一条数据
mysql> insert into account values(1,'张三',1234.5);
Query OK, 1 row affected (0.00 sec)
--6、创建一个保存节点save2
mysql> savepoint save2;
Query OK, 0 rows affected (0.00 sec)
--7、在当前表中再次插入一条数据
mysql> insert into account values(2,'李四',998.561);
Query OK, 1 row affected, 1 warning (0.00 sec)
--8、创建一个保存节点save3
mysql> savepoint save3;
Query OK, 0 rows affected (0.00 sec)
--9、在当前表中再次插入一条数据
mysql> insert into account values(3,'王五',653.25);
Query OK, 1 row affected (0.00 sec)
--10、回滚到保存点save3
mysql> rollback to save3;--如果全部回滚,可以直接rollback;
Query OK, 0 rows affected (0.00 sec)
--11、提交以结束本次事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

User: root

--当上方用户执行完第三步时,让另一个用户开始一个事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--当上方用户执行完第五步时,root用户查看表发现表中存在一条数据
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
+----+--------+---------+
1 row in set (0.00 sec)
--当上方用户执行完第九步时,root用户查看表发现表中存在三条数据
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
|  3 | 王五   |  653.25 |
+----+--------+---------+
3 rows in set (0.00 sec)
--当上方用户执行完第十步时,root用户查看表发现王五没了
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
+----+--------+---------+
2 rows in set (0.00 sec)
--提交以结束本次事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

1. If in a transaction, the user finally commits the transaction, then the data modifications in this transaction will be persisted by MySQL, and there is no chance to roll back.

2. If you roll back from save3 to save1 and find that you have rolled too far, you cannot roll forward from save1 to save3. MySQL will prompt SAVEPOINT s3 does not exist.

3. If the transaction is not committed after starting the transaction, but the client crashes, MySQL will automatically roll back

User: jly

--1、启动事务并插入数据
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
mysql> select* from account;
Empty set (0.01 sec)
mysql> insert into account values(1,'张三',1234.5);
Query OK, 1 row affected (0.01 sec)
mysql> insert into account values(2,'李四',998.561);
Query OK, 1 row affected, 1 warning (0.02 sec)
mysql> insert into account values(3,'王五',653.25);
Query OK, 1 row affected (0.00 sec)
--2、未commit,使用ctrl+\终止MySQL
mysql> Aborted

User: root

--1、启动事务
mysql> begin;
--当上方用户执行完第一步时,查看表
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
|  3 | 王五   |  653.25 |
+----+--------+---------+
3 rows in set (0.00 sec)
--当上方用户执行完第二步时,查看表,发现数据回退
mysql> select* from account;
Empty set (0.00 sec)

If the transaction is not committed after starting the transaction, but the client crashes or you forcefully close the client, MySQL will automatically roll back

1. Autocommit will not affect the submission of transactions started after begin. You must enter commit after using begin to make the data persistent.

2. The essence of a single SQL statement is a transaction, and its persistence is related to autocommit. Autocommit is ON, which means that the single SQL statement will be automatically submitted without manual commit. Otherwise, manual commit is required to make the data persistent. (There are special cases for select because MySQL has MVCC)

3. Transactions can be rolled back manually. At the same time, MySQL will automatically roll back when the operation is abnormal.

4. We can see the atomicity (rollback) and durability (commit) of the transaction itself

3. Transaction isolation level

1. Isolation

1. The MySQL service may be accessed by multiple client processes (threads) at the same time, and the access is conducted in a transactional manner.

2. A transaction may be composed of multiple SQL statements, which means that any transaction has stages before execution, during execution, and after execution. The so-called atomicity actually means that the user layer can see either before execution or after execution. If a problem occurs during execution, you can roll back at any time. Therefore, the characteristic of a single transaction to users is atomicity .

3. However, all transactions must have an execution process, so when multiple transactions execute multiple SQLs respectively, there may still be mutual influence. For example: multiple transactions access the same table or even the same row of data at the same time.

4. In the database, in order to ensure that there is as little interference as possible during transaction execution, there is an important feature: isolation.

5. In the database, there is an important feature that allows transactions to be interfered with to varying degrees: isolation level.

2. Isolation level

These four points are all about read and write concurrency:

Read Uncommitted: At this isolation level, all transactions can see the uncommitted execution results of other transactions. (It is impossible to use this isolation level in actual production), but it is equivalent to no isolation, and there will also be many concurrency problems, such as dirty reads, phantom reads, non-repeatable reads, etc. For the convenience of experiments, we used It's this isolation.

Read Committed: This isolation level is the default isolation level of most databases (not the MySQL default). It meets the simple definition of isolation: a transaction can only see changes made by other committed transactions. This isolation level will cause non-repeatable reads , that is, when a transaction is executed, if you select multiple times, you may get different results.

Repeatable Read [Repeatable Read]: This is the default isolation level of MySQL. It ensures that the same data row will be seen when the same transaction reads operation data multiple times during execution. But some databases have phantom reading problems. (MySQL does not)

Serializable: This is the highest isolation level for transactions. It solves the problem of phantom reads by forcing transactions to be ordered so that they cannot conflict with each other. It adds a shared lock on each data row read. However, it may cause timeouts and lock competition (this isolation level is too extreme and is basically not used in actual production)

How to implement isolation level: Isolation is basically implemented through locks. Different isolation levels require different lock usage. Common ones include table locks, row locks, read locks, write locks, gap locks (GAP), Next-Key locks (GAP+row locks), etc. 

3. Isolation viewing and setting

3.1 Isolated viewing

--查看全局的隔离级别
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED      |
+-----------------------+
1 row in set, 1 warning (0.02 sec)

--查看当前会话的隔离级别
mysql> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-UNCOMMITTED       |
+------------------------+
1 row in set, 1 warning (0.00 sec)

--默认同上
mysql> select @@tx_isolation;
+------------------+
| @@tx_isolation   |
+------------------+
| READ-UNCOMMITTED |
+------------------+
1 row in set, 1 warning (0.00 sec)

The isolation level of the current session is based on the global isolation level. 

3.2 Set isolation level

grammar:

--设置当前会话 or 全局隔离级别语法
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL {READ UNCOMMITTED | READ
COMMITTED | REPEATABLE READ | SERIALIZABLE}

Set the session isolation level to read-committed: 

mysql> set session transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
--修改后,全局隔离级别没有变,会话隔离级别被修改为读提交
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| READ-UNCOMMITTED      |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-COMMITTED         |
+------------------------+
1 row in set, 1 warning (0.00 sec)

Change the isolation level to read-commit. At this time, the isolation levels of other users will not be modified. This only changes the isolation level of the current user.

After logging in again, the session's isolation level will be reconfigured according to the global isolation level.

Set the global isolation level to serialized:

mysql> set global transaction isolation level SERIALIZABLE;
Query OK, 0 rows affected (0.01 sec)

--修改全局的隔离级别只影响全局的,当前会话和默认的隔离级别不变
mysql> select @@global.tx_isolation;
+-----------------------+
| @@global.tx_isolation |
+-----------------------+
| SERIALIZABLE          |
+-----------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@session.tx_isolation;
+------------------------+
| @@session.tx_isolation |
+------------------------+
| READ-COMMITTED         |
+------------------------+
1 row in set, 1 warning (0.00 sec)

mysql> select @@tx_isolation;
+----------------+
| @@tx_isolation |
+----------------+
| READ-COMMITTED |
+----------------+
1 row in set, 1 warning (0.00 sec)

When a session modifies the global isolation level, the global isolation levels of all other sessions will be modified at the same time.

On subsequent logins, the session and default isolation level will reference the global isolation level setting.

Try to ensure that the isolation level is consistent, and do not change the isolation level of the transaction when you have nothing to do.

4. Detailed explanation of the four isolation levels

4.1Read Uncommitted【Read Uncommitted】

--先设置当前的全局隔离级别为读未提交,再退出MySQL重新登录一下让其生效
mysql> set global transaction isolation level read uncommitted;
Query OK, 0 rows affected (0.01 sec)

The second chapter of this article uses reading uncommitted as an example.

Start transactions in multiple parallel sessions. Even if a transaction changes the database without commit, other transactions can see the data it modified in real time. When a transaction is executing, it reads updated (or other operations) but uncommitted data from another executing transaction. This unreasonable phenomenon is called dirty read.

Other unreasonable phenomena of uncommitted reading include non-repeatable reading and phantom reading.

Read uncommitted has almost no locking. Although it is efficient, it has too many problems and is not recommended.

4.2 Read Committed

User: jly

--1、先设置当前的全局隔离级别为读提交,再退出MySQL重新登录一下让其生效
mysql> set global transaction isolation level read committed;
Query OK, 0 rows affected (0.00 sec)
--2、开始事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--3、插入一条数据
mysql> insert into account values (4,'赵六',123);
Query OK, 1 row affected (0.01 sec)
--4、提交
mysql> commit;
Query OK, 0 rows affected (0.02 sec)

User: root

--开始事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--当上方用户执行完第3步时,查看表数据,并没有看到插入的赵六的信息
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
|  3 | 王五   |  653.25 |
+----+--------+---------+
3 rows in set (0.01 sec)
--当上方用户执行完第4步时,查看表数据,能够看到赵六的信息
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
|  3 | 王五   |  653.25 |
|  4 | 赵六   |  123.00 |
+----+--------+---------+
4 rows in set (0.02 sec)

Through experiments, we can find the read-commit level. Before transaction A commits the transaction, the modifications made will not be seen by other transactions. Once transaction A initiates the commit, other transactions can see the modifications made by transaction A to the data. This causes other transactions to find different data when they select to view the database at different points in time. This phenomenon is called non-repeatable reading . (Reads within a transaction are not atomic)

4.3 Repeatable Read【Repeatable Read】

Repeatable read is MySQL's default isolation level.

User: jly

--1、重启MySQL
systemctl restart mysqld
--2、重启后查看默认的隔离级别为读提交
mysql> select @@tx_isolation;
+-----------------+
| @@tx_isolation  |
+-----------------+
| REPEATABLE-READ |
+-----------------+
1 row in set, 1 warning (0.00 sec)
--3、启动事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--4、将id为2的名字(李四)修改为张三
mysql> update account set name='张三' where id=2;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
mysql> select* from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 张三   |  998.56 |
|  3 | 王五   |  653.25 |
|  4 | 赵六   |  123.00 |
+----+--------+---------+
4 rows in set (0.01 sec)
--5、提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)

User: root

--启动事务
mysql> begin;
Query OK, 0 rows affected (0.00 sec)
--当上方用户执行完第4步时,查看表数据,李四并没有被修改为张三
mysql> select *from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 李四   |  998.56 |
|  3 | 王五   |  653.25 |
|  4 | 赵六   |  123.00 |
+----+--------+---------+
4 rows in set (0.00 sec)
--提交事务
mysql> commit;
Query OK, 0 rows affected (0.00 sec)
--当上方用户执行完第5步时,查看表数据,李四被修改为张三
mysql> select *from account;
+----+--------+---------+
| id | name   | blance  |
+----+--------+---------+
|  1 | 张三   | 1234.50 |
|  2 | 张三   |  998.56 |
|  3 | 王五   |  653.25 |
|  4 | 赵六   |  123.00 |
+----+--------+---------+
4 rows in set (0.00 sec)

Under this isolation level, one MySQL transaction will not affect the reading of another transaction before commit. This isolation level is called repeatable read.

In the case of repeatable reading, a general database cannot shield the data inserted by other transactions, because the isolation implementation is completed by locking the data, and the data to be inserted does not exist, so general locking cannot shield this type of data. The problem is that although most of the content is repeatable, the insert data is read out in a repeatable state. When searching multiple times, more new records will be found, which is like an illusion. This phenomenon is called phantom read (mainly for insertion scenarios) . Obviously, MySQL solved the phantom read problem when it was at the RR level (the solution was to use Next-Key locks (GAP + row locks).) 

4.4 Serialization [Serializable]

Serialization means locking all transactions and queuing up the execution of transactions one by one, which leads to low efficiency.

When transaction A and transaction B are opened, the two transactions will use shared locks for simultaneous selective reading and will not be serialized; if there are updates and other operations in transaction A, A will be blocked until transaction B is submitted. If transaction A blocks for too long, the current transaction will exit due to lock waiting timeout.

Guess you like

Origin blog.csdn.net/gfdxx/article/details/131447315