简介:作者:孤独烟 出处: http://rjzheng.cnblogs.com/大家在面试中一定碰到过说说事务的隔离级别吧?老实说,事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了 ...
作者:孤独烟 出处: http://rjzheng.cnblogs.com/大家在面试中一定碰到过 说说事务的隔离级别吧?老实说,事务隔离级别这个问题,无论是校招还是社招,面试官都爱问!然而目前网上很多文章,说句实在话啊,我看了后我都怀疑作者弄懂没!因为他们对可重复读(Repeatable Read)和串行化(serializable)的解析实在是看的我一头雾水!再加上很多书都说可重复读解决了幻读问题,比如《mysql技术内幕--innodb存储引擎》等,不一一列举了,因此网上关于事务隔离级别的文章大多是有问题的,所以再开一文说明!本文所讲大部分内容,皆有官网作为佐证,因此对本文内容你可以看完后,你完全可以当概念记在脑海里,除非官网的开发手册是错的,否则应当无误!另外,本文会重点说一下 可重复读(Repeatable Read)是否真的解决幻读的问题!正文开始我先提一下,根据事务的隔离级别不同,会有三种情况发生。即脏读、不可重复读、幻读。这里我先不提这三种情况的定义,后面在讲隔离级别的时候会补上。这里,大家记住一点,根据脏读、不可重复读、幻读定义来看(自己总结,官网没有),有如下包含关系: dirty readAn operation that retrieves unreliable data, data that was updated by another transaction but not yet committed.翻译过来就是 检索操作出来的数据是不可靠的,是可以被另一个未提交的事务修改的!你会发现,我们的演示结果和官网对脏读的定义一致。根据我们最开始的推理,如果存在脏读,那么不可重复读和幻读一定是存在的。2、读已提交(READ_COMMITTED)这个也能看的出来,一个事务能读到另一个事务已提交的数据!为了便于说明,我简单的画图说明! non-repeatable readThe situation when a query retrieves data, and a later query within the same transaction retrieves what should be the same data, but the queries return different results (changed by another transaction committing in the meantime).翻译过来就是 一个查询语句检索数据,随后又有一个查询语句在同一个事务中检索数据,两个数据应该是一样的,但是实际情况返回了不同的结果。!ps:作者注,这里的不同结果,指的是在行不变的情况下(专业点说,主键索引没变),主键索引指向的磁盘上的数据内容变了。如果主键索引变了,比如新增一条数据或者删除一条数据,就不是不可重复读。显然,我们这个现象符合不可重复读的定义。下面,大家做一个思考:
phantomA row that appears in the result set of a query, but not in the result set of an earlier query. For example, if a query is run twice within a transaction, and in the meantime, another transaction commits after inserting a new row or updating a row so that it matches the WHERE clause of the query.翻译过来就是 在一次查询的结果集里出现了某一行数据,但是该数据并未出现在更早的查询结果集里。例如,在一次事务里进行了两次查询,同时另一个事务插入某一行或更新某一行数据后(该数据符合查询语句里where后的条件),并提交了!好了,接下来上图,大家自己评定该现象是否符合幻读的定义
By default, InnoDB operates in REPEATABLE READ transaction isolation level. In this case, InnoDB uses next-key locks for searches and index scans, which prevents phantom rows (see Section 14.7.4, “Phantom Rows”).按照原本这句话的意思,应该是InnoDB默认用了REPEATABLE READ。在这种情况下,使用next-key locks解决幻读问题!结果估计,某个国内翻译人员翻着翻着变成了InnoDB默认用了REPEATABLE READ。在这种情况下,可以解决幻读问题!然后大家继续你抄我,我抄你,结果你懂的!显然,漏了"使用了next-key locks!"这个条件后,意思完全改变,我们在该隔离级别下执行语句 select * from tx_tb where pId >= 1;是快照读,是不加任何锁的,根本不能解决幻读问题,除非你用 select * from tx_tb where pId >= 1 lock in share mode;这样,你就用上了next-key locks,解决了幻读问题!4、串行读(SERIALIZABLE_READ)在该隔离级别下,所有的select语句后都自动加上lock in share mode。因此,在该隔离级别下,无论你如何进行查询,都会使用next-key locks。所有的select操作均为当前读! |