MySQL四种事务隔离级别

事务是一系列数据操作的过程。事务具有四个特征,分别足原子性(Atomicity )、一致性(Consistency )、隔离性(Isolation) 和持久性(Durability),简称为事务的ACID特性。

先了解几种场景的名词定义:

脏读(Drity Read):A事务更新了一份数据,但是未提交(commit),B事务此时读到了这份未提交的更新数据,称之为脏读。如果事务A不回滚,基本上也没什么问题,如果事务A回滚了,问题可能就会非常大。

不可重复读(Non-repeatable read):A事务在执行过程中,B事务对数据进行了修改或删除(已commit),导致A两次读取的数据不一致;重点在于update和delete(锁行即可解决)。

幻读(Phantom Read):A事务在执行过程中,B事务新增了符合A事务要查询的数据,导致A两次读取的数据不一致;重点在于insert(需要锁表解决)。

Mysql的四种隔离级别

隔离级别依次递增,通过select @@tx_isolation;可显示当前的隔离级别。

Read Uncommitted(读未提交)

在该隔离级别,mysql允许脏读(Dirty Read),即可以读到其他事务没有提交(commit)的内容。

Read Committed(读已提交)

只能读到其他事务已经提交的内容,因此不会出现脏读,但是会出现可不重复读、幻读

Repeatable Read(可重读)

解决了脏读、不可重复读的问题,但是会有可能出现幻读。这是MySQL默认的事务隔离级别。

Serializable(可串行)

不同级别会造成的问题

image-20200724160304859

更新,关于可重读级别下的幻读问题

今天我在v2ex上发现有人讨论幻读的问题,发现第三级别下,并不会出现幻读问题,来看看我的操作:

no. session 1 session 2
1 begin; begin;
2 select * from test; // 三条记录
3 insert into test(content, title) values (2,2);
4 commit;
5 select * from test; // 依然三条记录

但是先不要慌,我们尝试一下update操作:

no. session 1 session 2
6 update test set content = ” where id = 4; // 显示成功了一条!
6 select * from test; // 发现session1中插入的那条出来了,神奇不?!

所以对于MySQL5.7和后续版本(8.0),如果只是select,已经跟不会出现幻读了,但是如果需要执行update等操作,那就要注意了。

关于事务的一些SQL操作

查询事务当前的隔离级别:

select @@tx_isolation;
/*
输出结果:
+-----------------+
| @@tx_isolation |
+-----------------+
| REPEATABLE-READ |
+-----------------+
*/

设置事务隔离级别:

-- 设置事务隔离级别为 read committed,仅在本次会话中生效
set session transaction isolation level read committed;

或者可以修改 my.cnf 配置文件使其永久生效:

[mysqld]
transaction-isolation = REPEATABLE-READ

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注