事务的隔离级别是用来调节数据库的并发性和数据的可靠性之间的平衡的工具。MySQL支持所有四种标准的隔离级别,Repeatable Read,Read Commited,Read Uncommited, Serializable。他默认的隔离级别是Reapeatable Read。下面来说一下不同的隔离级别运作的原理,与锁在其中产生的作用。
- Repeatable Read 可重复读
意思是同一事务中,多次对同一记录读取时,所读取到的值是一样的。这里涉及到一个InnoDB的Multi-Version的概念,正是它,实现了在同一事务中的一致性读取。同一事务多次读取的时候,都是读取的同一版本的数据快照,所以有可能在事务进行中,其他事务已经对记录做出来了变更,但原事务还是读取到旧版本的记录。
- Multi-Version
InnoDB是一个使用了多版本技术的数据库,当一条记录被修改或删除时,在MySQL Tablespace 中一个叫回滚段(Rollback Segment)的数据结构中的重做日志(Redo log Segment)中,会存储该记录恢复到之前的样子的信息。存储这个信息的作用有两个, 一个是回滚的时候恢复数据,另外一个作用,就是为了能够在同一事务中实现一致读 (Consistent Read)。
MySQL的Repeatable Read隔离级别,同时也部分解决了幻读的问题。为什么说是部分呢?因为对于普通的Select ,同一事务中查询两次,并不保证记录数一致,因为不会加间隙锁(Gap Lock)或临键锁(Next-key Lock)来防止别的事务插入记录。
然而对于加锁的读( select ... lock in share mode 或者 select ... for update) 或者update和delete,MySQL会根据查询条件是否为范围查询,来加间隙锁(Gap Lock)或临键锁(Next-key Lock),以防止幻读的发生。也就是说,在事务结束前,其他事务锁住的区间都不能进行插入操作。
- Read Committed 提交读
意思是在同一事务中,两次读取到的都是已提交的最新版本的数据,所以两次读取的值可能会有不同。它只解决了脏读的问题,不会读取到未提交的数据。
对于加锁的读( select ... lock in share mode 或者 select ... for update) 或者update和delete,MySQL只会对满足查询条件的记录加锁,不会在索引之前加临键锁或者间隙锁。所以不会防止其他事务插入数据,会导致幻读的发生。
- Read Uncommitted 未提交读
会读取到未提交的记录,其他的和Read Committed一致。
- SERIALIZABLE 序列化
这个级别和Repeatable Read差不多,但是在Select查询的时候,auto commit关闭的状况下,默认会在select 语句之后加上lock in share mode。也就是说,Select查询之间不会阻塞,但是碰到update,delete等加排他锁的语句时,会阻塞,等待获取锁。