一.分类
1.按锁的粒度可以分为:表锁,页锁,行锁,全局锁。
2.按照锁机制分类有:共享(读)锁
,排他(写)锁
,意向共享(读)锁
,意向排他(写)锁
。
3.以及Innodb引擎为解决幻读等并发场景下事务存在的数据问题,引入的Record Lock
(行记录锁)、Gap Lock
(间隙锁)、Next-key Lock
(Record Lock + Gap Lock结合)等。
二.粒度分类
1.表锁
锁定整张表,锁定粒度大。
优势:实现逻辑简单,带来的系统负面影响最小,获取和释放锁很快。
劣势:由于锁定粒度大,引起系统资源争用的概率变高,并发度降低。
2.行锁
锁定粒度到行,innodb使用。
优势:发生资源争用的概率降低,系统的处理并发事务的能力变强
劣势:由于锁定粒度小,获取锁和释放锁带来系统消耗更大,行级锁也最容易发生死锁
innodb什么时候使用行锁
:只有通过索引条件检索数据,InnoDB才会使用行级锁,否则,InnoDB将使用表锁。select
时,where条件中要有确定的索引条件,update和delete
时,MySQL不仅锁定WHERE条件扫描过的所有索引记录,而且会锁定相邻的键值,即所谓的next-key locking。
3.全局锁
首先全局锁
,是对整个数据库实例加锁。使用场景一般在全库逻辑备份时。MySQL提供加全局读锁的命令:Flush tables with read lock (FTWRL)
这个命令可以使整个库处于只读状态。使用该命令之后,数据更新语句、数据定义语句和更新类事务的提交语句等修改数据库的操作都会被阻塞。
三.锁机制分类
1.共享锁(share lock)
又称为读锁
,加锁后其他事务可以读,但是不能写。允许不同事务之前共享加锁读取,但不允许其它事务修改或者加入排他锁。
select * from xxx lock in share mode;
简单的select * from xx
不会加任何锁。
2.排他锁(exclusive lock)
排他锁又称写锁、独占锁
,如果事务T对数据A加上排他锁后,则其他事务不能再对A加任何类型的封锁。获准排他锁的事务既能读数据,又能修改数据。
select * from xxx for update;
update
insert
delete
以上操作会给涉及的数据加上排他锁。
3.意向锁
分类:意向共享锁&意向排他锁
产生方式
:是一种表锁
,由数据库引擎自己维护,用户无需手动操作。在为数据库加共享/排他锁褰,innodb会先获取该行数据所在表的对应意向锁。
解决的问题
:如果另一个任务试图在该表级别上应用共享或排它锁,则受到由第一个任务控制的表级别意向锁的阻塞。第二个任务在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁。提高了加锁的效率。
与其他锁的阻塞情况
:意向锁之间不会互相阻塞,意向锁不会阻塞行级的共享锁和排他锁,但是会和表级的共享锁和排他锁互斥(IS和表级的共享锁不会)。
四.Innodb中使用的锁
1.record lock
锁定一个记录上的索引,而不是记录本身。
如果表没有设置索引,InnoDB 会自动在主键上创建隐藏的聚簇索引,因此 Record Locks 依然可以使用。
2.gap lock
在索引记录之间的间隙中加锁,或者是在某一条索引记录之前或者之后加锁,并不包括该索引记录本身。
3.next-key lock
Record lock和gap lock的结合,即除了锁住记录本身,还要再锁住索引之前的间隙,范围为前开后闭。在rr级别下,默认的加锁类型就是next-key lock。
4.什么时候使用哪个锁
1)对主键等值加锁,且值存在时,会对表添加意向锁,同时会对主键索引添加行锁(record lock)—— 索引上的等值查询,在给唯一索引加锁时,next-key lock会退化为行锁,因为主键是唯一的。
2)对主键等值加锁,在数据不存在时,会锁住该主键查询条件所在的间隙(gap lock)—— 索引上的等值查询, 继续向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
3)范围查找时,先找到复核条件的一行数据,再向右查找,向右查找时加的锁不会退化为间隙锁。
五.乐观锁和悲观锁
乐观锁
,认为大部分情况不会出现冲突,通过版本号对比来决定版本,在mysql中体现:多版本并发控制(MVCC)。
悲观锁
,认为数据出现冲突的可能性大,加锁阻塞其他线程对数据的修改。