create table t1(
c1 int(10) unsigned not null default ‘0‘,
c2 int(10) unsigned not null default ‘0‘,
c3 int(10) unsigned not null default ‘0‘,
c4 int(10) unsigned not null default ‘0‘,
primary key(c1),
key c2(c2)
) engine=innodb
| c1 | c2 | c3 | c4 |
+-----+-----+-----+-----+
| 0 | 0 | 0 | 0 |
| 1 | 1 | 1 | 0 |
| 3 | 3 | 3 | 0 |
| 4 | 2 | 2 | 0 |
| 6 | 2 | 2 | 0 |
| 8 | 6 | 6 | 0 |
| 10 | 4 | 4 | 0 |
隔离级别为RR
例子1:
T1 | T2 |
begin | begin |
select * from t1 where c1=3 for update
| c1 | c2 | c3 | c4 | +-----+-----+-----+-----+ | 3 | 3 | 3 | 0 | |
|
select * from t1 where c1=3 lock in share mode 这种情况会被阻塞,因为T1是排它锁,T2是共享锁,排它锁和共享锁是互斥的。 |
例子2:
T1 | T2 |
begin | begin |
select * from t1 where c1=3 lock in share mode
| c1 | c2 | c3 | c4 | +-----+-----+-----+-----+ | 3 | 3 | 3 | 0 | |
|
select * from t1 where c1=3 for update 这种情况会被阻塞,因为T1是共享锁,T2是排它锁,排它锁和共享锁是互斥的。 |
例子3:
T1 | T2 |
begin | begin |
select * from t1 where c1=3 for update
| c1 | c2 | c3 | c4 | +-----+-----+-----+-----+ | 3 | 3 | 3 | 0 | |
|
select * from t1 where c1=3 这种情况不会被阻塞,因为T2是一次性非锁定读。 |
例子4:
T1 | T2 |
begin | begin |
select * from t1 where c3=7 lock in share mode | |
select * from t1 where c3=10 for update 备注:c3无索引 这种情况会被阻塞,因为T2中,C3无索引,所以会升级为表级锁。 |
例子5:
T1 | T2 |
begin | begin |
select * from t1 where c3=7 lock in share mode | |
select * from t1 where c1=6 for update 备注:c1是主键 这种情况会被阻塞,因为T1中c3无索引,会造成表级锁。 |
例子6:
T1 | T2 |
begin | begin |
select * from t1 where c2=2 and c3=5 for update | |
select * from t1 where c2=2 and c3=7 for update 备注:c2列上有索引,c3列上无索引,c3=7不存在 这种情况会被阻塞,因为c2=2,此列上有索引,这个记录上会加一个排它锁。T1和T2中的C3没有索引,所以不能判断是不是同一个记录,他只有将所有记录都加上锁。 |
例子7:
T1 | T2 |
begin | begin |
select * from t1 where c2=2 and c3=5 for update | |
select * from t1 where c2=3 and c3=7 for update 备注:c2列上有索引,c3列上无索引,c3=7不存在 这种情况不会被阻塞,锁是基于索引的,T1中c2=2和 T2中c2=3并不是同一条数据。 |
例子8:
T1 | T2 |
begin | begin |
select * from t1 where c2=2 and c3=2 for update | |
select * from t1 where c1=4 and c3=10 for update 备注:c1是主键,c2是普通索引,c3列上无索引 这种情况会被阻塞,因为在c2=2上加锁,最终会回溯到主键c1=4上也加锁。 |
例子9:
T1 | T2 |
begin | begin |
update t1 set c4=20 where c2>=4 | |
select * from t1 where c2>=4 | select * from t1 where c1=7 for update 备注:c1列是主键,c2列是普通索引,T1影响了两行。 这种情况不会被阻塞,T1锁定的范围是c2>=4的所有记录,且是next lock,以及c1=8 & c1=10的record lock,T2锁定的范围是c1=7的 record lock。 |
例子10:
T1 | T2 |
begin | begin |
update t1 set c4=20 where c2>=4 | |
select * from t1 where c2>=4 | insert into t1 select 7,5,10,10 备注:c1列是主键,c2列是普通索引,T1影响了两行。 这种情况会被阻塞,T1锁定的范围是c2>=4的所有记录,且是next lock,以及c1=8 & c1=10的record lock, 在T2中 5>4,所以会被阻塞。 |
例子11:
T1 | T2 |
begin | begin |
update t1 set c4=20 where c2>=4 | |
select * from t1 where c2>=4 | insert into t1 select 7,2,10,10 备注:c1列是主键,c2列是普通索引,T1影响了两行。 这种情况不会被阻塞,T1锁定的范围是c2>=4的所有记录,且是next lock,以及c1=8 & c1=10的record lock, 在T2中 2<4,不管T1还是T2都不在范围内,所以不会被阻塞。 |
例子12:
T1 | T2 |
begin | begin |
update t1 set c4=20 where c1>=6 | |
insert into t1 select 9,9,9,9 备注:c1列是主键,c1=6已经存在 这种情况会被阻塞,因为T1锁定的是所有c1>=6的范围record lock。 |
例子13:
T1 | T2 |
begin | begin |
insert into t1 select 9,9,9,9 | |
insert into t1 select 7,7,7,7 备注:c1列是主键,c1=7和c1=9的记录都不存在 这种情况不会被阻塞,因为C1和C2都不在同一个位置上面 |
例子14:
T1 | T2 |
begin | begin |
insert into t1 select 9,9,9,9 | |
insert into t1 select 9,9,9,9 备注:c1列是主键,c1=9的记录不存在 这种情况会被阻塞,因为C1和C2都在同一个位置上面 |