MySQL事务隔离级别

SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些是在事务内和事务间可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。

四种事务隔离级别简单说明:

READ UNCOMMITTED(读取未提交):

顾名思义,事务可以读取未提交的数据。在该隔离级别下,某一事务A中的修改,即使最终未提交,对其他事务B、C也都是可见的。也就是说,即使事务A中的修改ROLLBACK了,修改的数据也会被事务B和C读取到。这被称为脏读(Dirty Read),这会导致很多问题。性能上来说,READ UNCOMMITTED不比其他隔离级别好多少,但却没有其他隔离级别的很多好处,如果没有特别的必要,实际情况中很少使用。

测试:

read-uncommitted-demo

 

READ COMMITTED(读取已提交):

顾名思义,事务只读取已提交的数据,他是大多数数据库的默认隔离级别(但MySQL除外)。在该隔离级别下,某一事务A中的修改,只有最终提交了,对其他事务B、C也才是可见的。该隔离级别有时也称为不可重复读(NONREPEATABLE READ),因为同一事务中,前后两次查询的结果可能会不一致(其他事务可能在中途插入了新数据)。

测试:

read-committed-demo

REPEATABLE READ(可重复读):

它是MySQL的默认隔离级别。该隔离级别,保证了同一事务中,前后多次执行同一查询,结果是一致的。但是,可重复读依然无法解决幻读的(Phantom Read)问题。例如:事务A查询到表中共有1条记录,此时事务B插入了1条新纪录,事务A更新所有表记录时,发现共更新了2行,其中有一条幻行(Phantom Row)。InnoDB通过多版本并发控制(MVCC,Multiversion Concurrency Control),解决了幻读问题。

测试:

repeatable-read-demo

SERIALIZABLE(串行化):

SERIALIZABLE是最高的隔离级别,它强制事务串行执行,避免了幻读(Phantom Read)问题。SERIALIZABLE隔离级别会在读取的每行数据上加锁,这可能导致大量超时和锁争用。实际环境中很少使用该隔离级别,只有在非常需要保证数据一致性,同时可以接受无并发的情况,才考虑使用该隔离级别。

查询、设置事务隔离级别:

-- 查看隔离级别
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;

-- 设置隔离级别
SET SESSION TRANSACTION ISOLATION LEVEL read uncommitted;
SET SESSION TRANSACTION ISOLATION LEVEL read committed;
SET SESSION TRANSACTION ISOLATION LEVEL repeatable read;
SET SESSION TRANSACTION ISOLATION LEVEL serializable;

 


————————————————————————-
|   隔离级别   |   脏读可能性   |   不可重复读可能性   |   幻读可能性     |     加锁读     |
————————————————————————-
| 读取未提交 |        Yes         |            Yes             |          Yes         |       No       |
| 读取已提交 |         No         |             Yes            |          Yes         |       No       |
|  可重复读   |         No         |              No            |          Yes         |       No       |
|   串行化     |          No        |              No            |           No         |       Yes      |
%1 $ S

发表回复