MySQL选用可重复读之前一定要想到的事情(无索引加锁验证)
当前读(锁定读)加锁情况.
|
读提交 | 可重复读 |
主键索引 |
锁定主键索引 |
锁定主键索引 |
唯一索引 |
锁定唯一索引的值和主键索引的值 |
锁定唯一索引的值和主键索引的值 |
普通索引 |
锁定普通索引的值和主键索引的值 |
锁定普通索引的值和主键索引的值,普通索引增加间隙锁 |
无索引 |
锁定所有的主键索引,在服务器层对不符合条件的记录解锁 |
锁定所有的主键索引和主键索引的间隙 |
但是如何验证读提交隔离级别,会锁定所有主键主键,而在服务器层解锁呢?
http://blog.itpub.net/29254281/viewspace-1398273/
实验数据如下:
create table t
(
a int primary key,
b int,
c int
) engine=innodb;
insert into t
values
(1,10,10),
(3,10,20),
(5,20,30),
(7,20,40),
(9,20,50);
commit;
首先,可重复读隔离级别.
终端一:
select * from t where b=20 and c=30 for update;
终端二:
delete from t where b=20 and c=50;
阻塞
查看锁情况
select * from information_schema.innodb_locks;
可以看到锁定的数据是主键索引 1
这是因为终端一已经锁定了所有的主键索引和主键索引间隙.
终端二获取第一个主键索引就被阻塞.
同样的过程,改为读提交隔离级别.
终端一
select * from t where b=20 and c=30 for update;
终端二
delete from t where b=20 and c=50;
阻塞
查看锁情况
select * from information_schema.innodb_locks;
可以看到锁定了主键索引 5
这验证了何老师的说法,
就是在读提交隔离级别,对所有的主键索引上锁,在服务器层释放不符合条件的锁,
也就是说终端一锁定了所有的主键索引,在服务器层释放了其他主键索引的锁,只保留了a=5的锁.
终端二开始加锁,加到a=5的主键索引不能获取,所以阻塞
从现象看,如果终端一的语句不走二级索引或者主键索引,终端二的语句都会阻塞,
但是不同的是,可重复读锁定所有主键索引和主键索引间隙,
而读提交最终只会锁定相关记录的主键索引.
那么在读提交的隔离级别下,下面的语句不会阻塞
select * from t where a=1 for update;
而在可重复读隔离级别下,上面的语句就会阻塞.
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。