Mysql锁的种类以及加锁情况
- 锁的种类
- 按照锁粒度
- 按照是否可写
- 另外两个表级锁
- 加锁的情况
- 怎么上读锁或者写锁
- 关于是表锁还是行锁?
- for update锁的情况
锁的种类
按照锁粒度
表锁:
Mysql中锁定 粒度最大 的一种锁,对当前操作的整张表加锁,实现简单 ,资源消耗也比较少,加锁快,不会出现死锁 。
行锁:
行级锁能大大减少数据库操作的冲突。其加锁粒度最小,并发度高,但加锁的开销也最大,加锁慢,会出现死锁。 InnoDB支持的行级锁,包括如下几种。
- Record Lock: 对索引项加锁,锁定符合条件的行。其他事务不能修改和删除加锁项;【该锁是对索引记录进行加锁!锁是在加索引上而不是行上的】
- Gap Lock: 对索引项之间的“间隙”加锁,其他事务不能在锁范围内插入数据,这样就防止了别的事务新增幻影行
- Next-key Lock: 锁定索引项本身和索引范围。即Record Lock和Gap Lock的结合。可解决幻读问题。
按照是否可写
共享锁(s): 假设事务T1对数据A加上共享锁,那么事务T2可以读数据A,不能修改数据A。其它事务还是可以对A加共享锁的
排他锁(X): 假设事务T1对数据A加上排他锁,那么事务T2不能读数据A,不能修改数据A。其他事务不能再加任何锁
insert,delete,update在事务中都会自动默认加上排它锁【行级】,只有
LOCK TABLE … READ
和LOCK TABLE … WRITE
才能申请表级别的锁。
另外两个表级锁
另外两个表级锁:
- 意向共享锁(IS): 表示事务准备给数据行记入共享锁,事务在一个数据行加共享锁前必须先取得该表的IS锁。
- 意向排他锁(IX): 表示事务准备给数据行加入排他锁,事务在一个数据行加排他锁前必须先取得该表的IX锁。
- 这里的意向锁是表级锁,表示的是一种意向,仅仅表示事务正在读或写某一行记录,在真正加行锁时才会判断是否冲突。意向锁是InnoDB自动加的,不需要用户干预。
- IX,IS是表级锁,不会和行级的X,S锁发生冲突,只会和表级的X,S发生冲突
- 意向锁之间互不排斥,但除了 意向共享锁 与 共享锁兼容外,意向锁会与 共享锁 / 排他锁 互斥【此处的锁指的都是表级锁】
意向锁存在的目的?
假设事务T1,用排他锁来锁住了表上的几条记录,那么此时表上存在意向排它锁。那么此时事务T2要进行LOCK TABLE … WRITE的表级别锁的请求,可以直接根据意向锁是否存在而判断是否有锁冲突。
加锁的情况
首先我们要知道
- 只有在可重复读和串行化的隔离级别下才有gapLock。
- 串行化,该级别下读写串行化,且所有的select语句后都自动加上
lock in share mode
,即使用了共享锁。因此在该隔离级别下,使用的是当前读,而不是快照读
怎么上读锁或者写锁
上共享锁(读锁)的写法:lock in share mode
上排它锁(写锁)的写法:for update
关于是表锁还是行锁?
并不是用表锁来实现锁表的操作,而是利用了Next-Key Locks,也可以理解为是用了行锁+间隙锁来实现锁表的操作!
如果隔离级别为读未提交和读已提交,无论条件列上是否有索引,都不会锁表,只锁行!,因为没有gaplock
for update锁的情况
行锁情况:查询条件中为主键、索引字段,且索引不为null并且生效的情况下是行锁,索引字段检索多条时,也是行级锁,组合索引,也是行级锁
表锁:查询条件非主键、非索引字段,或者说索引未生效的情况下是表锁
无锁:查询无符合条件记录时,无锁