http://www.mysqlops.com/2012/05/19/locks_in_innodb.html#more-3169
这篇博客写的比较详细,下面主要是做一下测试对下面的矩阵进行验证
G I R N (已经存在的锁,包括等待的锁)
G + + + +
I - + + -
R + + - -
N + + - -
现在有数据库 id num
2 2
10 10
其中id为主键并带有唯一索引,num字段无索引
上面的文章主要写了查询中使用索引的情况,对于查询中不使用索引的情况 delete from test where num= 2 来说 ,会对表进行表锁定。
可以使用 show status like '%table_lock%' 查看,具体的表锁定实现机制暂时不清楚,在实验中验证 ,表锁定所有的行,表现为所有行的R锁,并组织插入行以及表锁定的获取并且阻塞表锁定,行锁定与表锁定的关系相同。
对于这段描述
Read Uncommitted和Read Committed时,不需要在间隙上加锁,Nexk-Key变成Record锁。我认为是错误的
下面这行是mysql官方文档的描述
在范围类型UPDATE
和DELETE语句,InnoDB必须对范围覆盖的间隙设置next-key锁定或间隙锁定以及其它用户做的块插入。这是很必要的,因为要让MySQL复制和恢复起作用,“幽灵行”必须被阻止掉。
我测试了一下 用例是这样 有 id,num 两个字段 有记录 (1,1) (20,20)
隔离级别为Read Committed 我使用 T1 执行 delete from test where id<15
有很多人认为 幻读在REPEATABLE_READ 里是不存在,还将原因归结到 多版本的作用,其实并不是这样的
在本例子中 delete from test where id <100 对于where子句使用索引的情况下 ,“幽灵行” 是被禁止的,因为 gap 是阻塞 insert的
但是对于 delete from test where num<100 的时候则是加 record锁定 ,record 与insert 是不阻塞的 ,这种情况会出现幻读
如 ti 执行 delete from test where num<100 t2 执行 insert into test values(10,10) 则会出现幽灵行 10.