间隙锁:为了避免幻读,引入了间隙锁,它锁定的记录范围,不包含记录本身,也就是不允许在范围内插入数据。根据搜索条件向上寻找靠近检索条件的的记录A作为左边区间,向下寻找靠近检索条件的记录B作为右边区间,即锁定区间为(A,B)。
锁的分类:
1:行锁:记录锁,间隙锁,next key lock临键锁(记录锁+间隙锁的组合)。间隙锁和临键锁防止幻读。
2:乐观锁,悲观锁。
3:读锁(共享锁,S锁),写锁(X锁,排他锁,独占锁,互斥锁)
4:mdl锁,意向锁:读的时候不允许其他事务修改表结构
【注】:不同的存储引擎支持的锁粒度是不一样的:InnoDB存储引擎表锁和行锁都支持;MyISAM只支持表锁。InnoDB存储引擎只有通过索引条件检索数据才使用行级锁,否则,InnoDB将使用表级锁;也就是说,InnoDB的行锁是基于索引的。
0: 记录锁。 有索引行锁才生效。
1: 间隙锁。注意,唯一索引,如果走等值判断,只会走记录锁,不会走间隙锁,只有用>,或者< 符合才走间隙锁。非唯一索引,如果等值判断和>,< 都一样会走间隙锁。
(1)例如:id作为主键,id>10才走间隙锁,如果id=10 就不会走间隙锁。这时候的间隙范围是(10,+∞),插入81就被间隙锁阻拦。直到查询的事务提交。
(2)no作为非唯一索引。no=9 时,间隙锁区间(8,89),插入no=80就失败。则证明非唯一索引时用=号,也会走间隙索引
2: next-key lock。上图中no=9,会走间隙锁,也会走记录锁,所以两者结合叫next-key lock,也叫做临键锁。起封锁范围包含索引记录,也包含索引区间。目的是防止幻读,如果把隔离级别将为RC(读已提交),临键锁则失效。
3:表锁。
由于myisam不支持事务和行锁(这是很多情况下选择innodb 的原因)。在对于innodb表,在绝大多数情况下都应该使用行级锁,但是在特殊情况下也可以考虑使用表级锁。
(1)第一种情况:事务需要更新大部分或者全部数据,表又比较大,如果使用默认的行锁,不仅事务执行效率低(因为不停地加锁,释放锁,就比较花时间),而且可能造成其他事务长时间锁等待和锁冲突,则应该使用表锁提高事务的执行速度。
(2)第二种情况:事务涉及多个表,比较复杂,容易引起死锁,引起大量事务回滚,这个情况也可以考虑一次性锁定事务所涉及的表,从而避免死锁,减少数据库因事务回滚带来的开销。
4: 读锁。读锁场景:lock in share mode
5: 写锁。
写锁场景select 。。。。for update,update table。。。。
6:MDL锁。开启查询事务的时候,不能更改表结构,比如不予许新增列行。
7:意向锁。 跟MDL一样,其他事务不能更改表结构。DDL语句是,增加或者删除字段等
8:悲观锁,乐观锁
9:锁等待
查询锁的超时时间:select @@innodb_lock_wait_timeout;
设置锁等待时间:set innodb_lock_wait_timeout = 30;
10:死锁