详解MySQL隔离级别
一个事务具有
ACID
特性,也就是(Atomicity、Consistency、Isolation、Durability,即原子性
、一致性
、隔离性
、持久性
),本文主要讲解一下其中的Isolation
,也就是事务的隔离性
。
概述
四种隔离级别分别是:
读未提交(read uncommitted)
- 一个事务还没提交时,它修改的数据都可以被别的事物看到。
读已提交(read committed)
- 一个事务提交之后,它修改的数据才会被别的事物看到。
可重复读(repeatable read)
- 一个事务执行过程中看到的数据,总是和这个事务开启时看到的数据是一致的。在可重复读的隔离级别下,未提交的事务对其他事务也是不可见的。
串行化(serializable)
- 数据的
读
和写
都会加锁
,读
会加读锁
,写
会加写锁
。当遇到读写锁冲突时,后访问的事务必须等前一个事务执行完成后,再继续执行。
- 数据的
以上四种隔离级别,由上往下隔离强度越来越大,但是执行效率会随之降低。在设置隔离级别时候,需要在
隔离级别
和执行效率
两者做平衡取舍。
为了便于理解,下面就举一个例子:
在不同隔离级别下,事务A
会有哪些不同的返回结果,也就是图中的V1
、V2
、V3
的返回值分别是什么。
- 如果隔离级别是读未提交,
事务B
修改后数据无需提交事务,就能被事务A
读取,所以V1
、V2
、V3
的值都是2
。 - 如果隔离级别是读已提交,
事务B
修改后需要提交后,修改后的数据才能被事务A
读取,所以V1
的值是1
,事务B
提交,事务A
读取修改后的数据,所以V2
的值是2
,V3
的值也是2
。 - 如果隔离级别是可重复读,整个事务看到的事务和事务开启时看到的数据是一致的,开启看到的数据是
1
,所以V1
、V2
的值都是1
,事务A提交之后,获取到修改后的数据,所以V3
的值是2
。 - 如果隔离级别是串行化,会被锁住,此时事务B对应的线程处于阻塞状态,直到事务A提交之后,事务B才会继续
将1改成2
。所以V1
、V2
的值是1
,V3
的值是2
。
MySQL
默认的隔离级别是可重复读
。
隔离级问题
先了解几个基本概念:
脏读:事务A
修改数据,事务B
读取了数据后事务A
报错回滚,修改的数据没有提交到数据库中,此时事务B
读取修改的数据就是一个脏读,也就是一个事务读取到另一个事务未提交的数据就是脏读。
不可重复读:事务A
在同一个事务上多次读取同一个数据,在事务A
还没有结束时,事务B
修改了该数据,由于事务B
的修改,导致事务A
两次读取的数据不一致,就出现了不可以重复读的现象。
幻读:事务A
根据条件查询得到N
条数据,但此时事务B
更改或者增加了M
条符合事务A
查询的条件的数据。这样当事务A
再次查询的时候发现会有N + M
条数据,产生了幻读。
几种隔离级别可能会有脏读
、不可重复读
或者幻读
的问题,它们之间的关系如下:
隔离级别 | 脏读 | 不可重复读 | 幻读 |
---|---|---|---|
读未提交 | √ | √ | √ |
读提交 | × | √ | √ |
可重复读 | × | × | √ |
串行化 | × | × | × |
相关文章