MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ)。
- 未提交读(READ UNCOMMITTED)。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据(脏读)。
- 提交读(READ COMMITTED)。本事务读取到的是最新的数据(其他事务提交后的)。问题是,在同一个事务里,前后两次相同的SELECT会读到不同的结果(不重复读)。在同一个事务生命周期内,也就是这个事务还未提交之前。如果另外一个事务,对数据进行了编辑(update)或者删除(delete)操作。那么A事务就会读取到。简单理解,就是在一个事务生命周期内,多次查询数据,每次都可能查出来的不一样。
- 可重复读(REPEATABLE READ)。在同一个事务里,SELECT的结果是事务开始时时间点的状态,因此,同样的SELECT操作读到的结果会是一致的。但是,会有幻读现象。幻读的结果其实和不可重复读是一样的表现,差异就在于,不可重复读,主要是针对其他事务进行了编辑(update)和删除(delete)操作。而幻读主要是针对插入(insert)操作。也就是在一个事务生命周期内,会查询到另外一个事务新插入的数据。
- 串行化(SERIALIZABLE)。读操作会隐式获取共享锁,可以保证不同事务间的互斥。
四个级别逐渐增强,每个级别解决一个问题。
- 脏读,最容易理解。另一个事务修改了数据,但尚未提交,而本事务中的SELECT会读到这些未被提交的数据。
- 不重复读。解决了脏读后,会遇到,同一个事务执行过程中,另外一个事务提交了新数据,因此本事务先后两次读到的数据结果会不一致。
- 幻读。解决了不重复读,保证了同一个事务里,查询的结果都是事务开始并且第一次查询时的状态(一致性)。但是,如果另一个事务同时提交了新数据,虽然本事务再次按照相同的条件查找会得到相同的结果集,但是本事务指定更新时(看了后面的演示你就会知道),就会“惊奇的”发现了这些新数据,貌似之前读到的数据是“鬼影”一样的幻觉。
不同的隔离级别有不同的现象,并有不同的锁定/并发机制,隔离级别越高,数据库的并发性就越差,4种事务隔离级别分别表现的现象如下表: