表记录如下:
pid(int) | name(varchar) | num(int) |
---|---|---|
1 | a | 100 |
2 | b | 200 |
3 | c | 300 |
7 | d | 200 |
1. select * from table where num = 200
不加任何锁,快照读
2. select * from table where num > 200
不加任何锁,快照读
3. select * from table where num = 200 lock in share mode
num = 200,对应pid为2,7两条记录,这两条记录的主键索引加S锁,采用当前读
4. select * from table where num > 200 lock in share mode
num > 200的记录只有pid = 3,该条记录主键索引加S锁,采用当前读
5. select * from table where num = 200 for update
num = 200,对应pid为2,7两条记录,这两条记录主键索引加X锁,采用当前读
6. select * from table where num > 200 for update
num > 200的记录只有pid = 3,该条记录主键索引加X锁,采取当前读
1. select * from table where pId = 2
不加任何锁,快照读
2. select * from table where pId > 2
不加任何锁,快照读
3. select * from table where pId = 2 lock in share mode
查询结果对应记录的主键索引加S锁,采用当前读
4. select * from table where pId > 2 lock in share mode
pid > 2,查询结果是3,7两条记录,在记录对应的主键索引加S锁,采用当前读
5. select * from table where pId = 2 for update
pid =2,对应记录的主键索引加X锁,采用当前读
6. select * from table where pId > 2 for update
pid > 2,查询结果是3,7两条记录,在记录对应的主键索引加X锁,采取当前读
1. select * from table where num = 200
不加任何锁,快照读
2. select * from table where num > 200
不加任何锁,快照读
3. select * from table where num = 200 lock in share mode
num = 200,对应pid为2,7两条记录,这两条记录的联合索引加S锁,回表去主键索引查询,对应记录主键索引加S锁,采用当前读
4. select * from table where num > 200 lock in share mode
num > 200的记录只有pid = 3,该条记录联合索引加S锁,回表去主键索引查询,对应记录主键索引加S锁,采用当前读
5. select * from table where num = 200 for update
num = 200,对应pid为2,7两条记录,这两条记录联合索引加X锁,回表去主键索引查询,对应记录主键索引加X锁,采用当前读
6. select * from table where num > 200 for update
num > 200的记录只有pid = 3,该条记录联合索引加X锁,回表去主键索引查询,对应记录主键索引加X锁,采取当前读
where条件非索引查询加锁方式和主键索引查询加锁方式很相似,都是查询结果的主键索引加锁。联合索引是在查询结果的联合索引和对应的主键索引加锁,加锁类型保持一致。
MySQL本身对非索引查询做了优化,非索引查询会扫描全表所有记录进行加锁,但是会把不满足条件的锁立即释放掉,所以看起来结果一样
1. select * from table where num = 200
RR:不加任何锁,快照读
Serializable:全表所有主键索引加S锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
2. select * from table where num > 200
RR:不加任何锁,快照读
Serializable:全表所有主键索引加S锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
3. select * from table where num = 200 lock in share mode
num = 200,对应pid为2,7两条记录,全表所有主键索引加S锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
4. select * from table where num > 200 lock in share mode
num > 200的记录只有pid = 3,全表所有主键索引加S锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
5. select * from table where num = 200 for update
num = 200,对应pid为2,7两条记录,全表所有主键索引加X锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
6. select * from table where num > 200 for update
num > 200的记录只有pid = 3,全表所有主键索引加X锁,在(-∞,1](1,2](2,3](3,7](7,+∞)上加Gap锁(间隙锁),相当于锁住整个表,采取当前读
1. select * from table where pId = 2
RR:不加任何锁,快照读
Serializable:在pid=2的主键索引加S锁,不存在Gap锁
2. select * from table where pId > 2
RR:不加任何锁,快照读
Serializable:pid > 2,查询结果是3,7两条记录,在对应记录主键索引加S锁,同时在(2,3](3,7](7,+∞)上加Gap锁,采用当前读
3. select * from table where pId = 2 lock in share mode
pid =2,对应记录的主键索引加S锁,不存在Gap锁,采用当前读
4. select * from table where pId > 2 lock in share mode
pid > 2,查询结果是3,7两条记录,在对应记录主键索引加S锁,同时在(2,3](3,7](7,+∞)上加Gap锁,采用当前读
5. select * from table where pId = 2 for update
pid =2,对应记录的主键索引加X锁,不存在Gap锁,采用当前读
6. select * from table where pId > 2 for update
pid > 2,查询结果是3,7两条记录,在对应记录主键索引加X锁,同时在(2,3](3,7](7,+∞)上加Gap锁,采用当前读
7. select * from table where pId = 6 [lock in share mode|for update]
该记录不存在,在(3,7]上加Gap锁
8. select * from table where pId > 18 [lock in share mode|for update]
该记录不存在,范围查询,在主键索引(7,+∞)上加gap lock
1. select * from table where num = 200
RR:不加任何锁,快照读
Serializable:num = 200,对应pid为2,7两条记录,在记录对应的联合索引上加S锁,对应主键索引加S锁,在联合索引(100,200](200,300]加上gap lock,采取当前读
2. select * from table where num > 200
RR:不加任何锁,快照读
Serializable:num > 200的记录只有pid = 3,在对应记录的联合索引上加S锁,对应主键索引上加S锁,在联合索引(200,300](300,+∞)上加Gap锁,采取当前读
3. select * from table where num = 200 lock in share mode
num = 200,对应pid为2,7两条记录,在记录对应的联合索引上加S锁,对应主键索引加S锁,在联合索引(100,200](200,300]加上gap lock,采取当前读
4. select * from table where num > 200 lock in share mode
num > 200的记录只有pid = 3,在对应记录的联合索引上加S锁,对应主键索引上加S锁,在联合索引(200,300](300,+∞)上加Gap锁,采取当前读
5. select * from table where num = 200 for update
num = 200,对应pid为2,7两条记录,在记录对应的联合索引上加X锁,对应主键索引加S锁,在联合索引(100,200](200,300]加上gap lock,采取当前读
6. select * from table where num > 200 for update
num > 200的记录只有pid = 3,在对应记录的联合索引上加X锁,对应主键索引上加S锁,在联合索引(200,300](300,+∞)上加Gap锁,采取当前读
7. select * from table where num = 250 [lock in share mode|for update]
查询结果为空,会在联合索引(200,300]上加Gap锁,采取当前读
8. select * from table where num > 400 [lock in share mode|for update]
查询结果为空,会在联合索引(400,+∞)上加Gap锁,采取当前读
select不显示加锁时,除了Serializable级别,其它级别不会加锁
参考:
https://www.cnblogs.com/rjzheng/p/9950951.html