1.Read Uncommitted(未提交读)
此隔离级别中,事务的修改对其他的事务也是可见的,事务可以读取未提交的数据,也称为脏读(Dirty Read)。很少使用此级别。
2.Read Commited(提交读)
大多数数据库系统默认使用该隔离级别(mysql不是),此隔离级别中事务从开始到提交数据之前,所有的操作对于其他事物都是不见的,也称作不可重复读(nonrepeatable),造成2次同样的查询可能会得到不同的结果。
3.Repeatable Read(可重复读)
可重复读解决了脏读的问题,保证了在同一个事务中多次读取同样的记录的结果是一致的。但是还发解决另外一个问题--幻读(Phantom Read):是指在读取某个范围的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎采用多版本并发控制(MVCC,Multiversion Concurrency Control)解决幻读的问题。其中MVCC大致可以理解为一个行级锁的变种,但是在很多情况下避免了加锁操作,因此开销更低。MVCC的实现是通过保存数据在某个时间点的快照来实现,因此,对于每个事务来说,看到的数据都是一致的。但是对于各个事务的开始时间不同,每个事务对同一张表的,同一时刻看到的数据可能是不一样的。
下面说下InnoDB的简化版MVCC的实现机制:
MVCC通过在每行记录后面保存两个隐藏的列来实现,分别代表,行的创建时间,行的过期时间,这里时间是指的系统版本号,而不是真正的时间。每开始一个新的事物,系统版本号会自动递增。下面列举在Repeatable Read隔离级别下,MVCC的具体操作:
SELECT:
InnoDB会根据以下两个条件检查每行记录:
a.InnoDB只查找版本早于当前事物版本的数据行(也就是行的系统版本号小于或等于事 物的系统版本号),这样可以保证事物读取的行,要么是在事物开始前就已经存在,要么是事务自身插入或修改的。
b.行的删除版本要么未定义,要么大于当前事物的版本号。这样可以确保事物读到行在事务开始前未被删除。
INSERT:
InnoDB为新插入的每一行保存当前系统版本号作为行版本号。
DELETE:
InnoDB为删除的每一行保存当前系统版本号作为行删除标识。
UPDATE:
InnoDB为插入的一行新纪录,保存当前系统保本号作为行版本号,同时保存当前系统版本号到原来的行作为行删除标识。
保存这两个额外的版本号,使大多数的读操作都可以不用加锁,是的读数据的操作简单,性能很好,并且会读取到符合标准的行,不足时每行记录都需要额外的存储空间,需要做更多的行检查及额外的维护操作。
4.Serializable(可串行化)
Serializable是最高的隔离级别,它通过强制事务串行执行,避免了前面的幻读问题,简单来说,Serializable会在读取的每一行的数据上都加锁,所以可能导致大量的超时和锁竞争。只有在非常确保数据一致性而且可以接受没有并发的情况下,才考虑采用该级别。