SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些是在事务内和事务间可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。
四种事务隔离级别简单说明:
READ UNCOMMITTED(读取未提交):
顾名思义,事务可以读取未提交的数据。在该隔离级别下,某一事务A中的修改,即使最终未提交,对其他事务B、C也都是可见的。也就是说,即使事务A中的修改ROLLBACK了,修改的数据也会被事务B和C读取到。这被称为脏读(Dirty Read),这会导致很多问题。性能上来说,READ UNCOMMITTED不比其他隔离级别好多少,但却没有其他隔离级别的很多好处,如果没有特别的必要,实际情况中很少使用。
测试:
READ COMMITTED(读取已提交):
顾名思义,事务只读取已提交的数据,他是大多数数据库的默认隔离级别(但MySQL除外)。在该隔离级别下,某一事务A中的修改,只有最终提交了,对其他事务B、C也才是可见的。该隔离级别有时也称为不可重复读(NONREPEATABLE READ),因为同一事务中,前后两次查询的结果可能会不一致(其他事务可能在中途插入了新数据)。
测试:
REPEATABLE READ(可重复读):
它是MySQL的默认隔离级别。该隔离级别,保证了同一事务中,前后多次执行同一查询,结果是一致的。但是,可重复读依然无法解决幻读的(Phantom Read)问题。例如:事务A查询到表中共有1条记录,此时事务B插入了1条新纪录,事务A更新所有表记录时,发现共更新了2行,其中有一条幻行(Phantom Row)。InnoDB通过多版本并发控制(MVCC,Multiversion Concurrency Control),解决了幻读问题。
测试:
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;