会命中d = 5的这一行,对应的主键是id等于5,因此在select语句执行完后d=5的这一行会加一个写锁,那么由于我们这个两阶段锁的协议呢,这个写锁会执行commit语句的时候进行一个释放。
在mysql innoDB的默认级别是可重复读
幻读:一个事务在前后两次查询同一个范围,或者说查询同一条语句的时候,后一次查询看到了前一次看不到的东西。
比如说,我有两个事务A和B,A执行了好多次
select * from t where d = 5 for update;
,B在这个表里insert了d=5的东西
,再次select的时候前一次执行和后一次执行看到的事务就不一样了(幻读)。在可重复读级别下,普通的查询是我们的快照查询,不会看到其它事务插入的数据。因此幻读在当前读下才会出现。
幻读仅指新插入的行,而不是update的行。
什么叫做当前读,当前读就指上面说的
for update
。虽然给这行加锁,也它也要说看到这行最新的数据,for update
这里也叫做我们的当前读。因为更新之前必须先查询一下当前的值。select in share modle
也是一个当前读的东西,指在更新之前必须先查询一下当前的值,所以叫做当前读。快照读只是在语句执行之前或者事务开始的时候,创建一个视图然后,后面的读呢都是基于这个视图来读的,像我们说的版本号似的,不会查询这个最新的值。for update
会查询最新的值,那出现幻读怎么办呢。for update
肯定是想把d = 5这行给锁住。有了幻读之后,这个语句的语义就被破坏了,这个锁的目的是保证数据的前后一致性,这样也破坏了这个一致性。幻读产生的原因是行锁只能锁住当前这一行,我还可以往里面再Insert东西,并不能去锁住其它的行。所以这里我们引出了另外的一个锁——间隙锁。
1 5 10 ,比如当前查询的这个值为5它会把前这个值的前一位和后一位都给锁住。