MySQL系列--锁的那些事儿

为什么会出现锁?

锁出现的原因:并发请求下的产物,锁机制用于管理对共享资源的并发访问
并发的任务对同一个临界资源进行操作,如果不采取措施,可能导致不一致,故必须进行并发控制(Concurrency Control)
并发控制保证数据一致性的常见手段有:

  • 锁(Locking)
  • 数据多版本(Multi Versioning)

InnoDB的锁类型

  • 共享锁(读锁Share Locks)
  • 排他锁(写锁eXclusive Locks)
  • 意向锁
  • MDL锁
共享锁(S锁)

允许多个事务对同一个行进行加锁,因为它是共享锁(锁兼容)
在除自己之外的其他事务持有锁时,UPDATE,DELETE操作会被阻塞
关键词:SELECT... LOCK IN SHARE MODE

排他锁(X锁)

对读取的行记录加上写锁,其他事务的锁都会被阻塞
关键词:SELECT... FOR UPDATE

意向锁

意向共享锁(IS):在给一个数据行加共享锁(S锁)前必须获取该表的IS锁
向排他锁(IX):在给一个数据行加排他锁(X锁)前必须获取该表的IX锁
意向锁是InnoDB自动加的,不需用户干预
为什么存在意向锁:
共享锁/排他锁是行锁,意向锁是表锁
InnoDB 支持多粒度锁,特定场景下,行级锁可以与表级锁共存
意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求

行级锁是施加在索引行数据上的锁

锁之间的兼容性

意向锁之间互不排斥,但除了 IS 与 S 兼容外,意向锁会与 共享锁 / 排他锁 互斥
IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突
锁的兼容性

InnoDB行锁的几种算法

  • Record Lock:单个行记录上的锁 。
  • Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
  • Next-Key Lock:Gap Lock + Record Lock,锁定一个范围,并且锁定记录本身。
  • Insert Intention Locks:插入意向锁。
Record Lock(记录锁)

单条索引记录上加锁,record lock锁住的永远是索引,而非记录本身,即使该表上没有任何索引,那么InnoDB会在后台创建一个隐藏的聚集主键索引,那么锁住的就是这个隐藏的聚集主键索引
所以说当一条SQL没有走任何索引时,那么将会在每一条聚集索引后面加X锁,这个类似于表锁,但原理上和表锁应该是完全不同的

Gap Lock(间隙锁)

间隙锁基于非唯一索引,它锁定一段范围内的索引记录
SELECT ... FOR UPDATE or LOCK IN SHARE MODE,InnoDB 会给符合条件的已有数据记录的索引项加锁
对于键值在条件范围内但并不存在的记录,叫做间隙(GAP),InnoDB 也会对这个间隙加锁。
UPDATE和DELETE时,除了对唯一索引的搜索外都会获取Gap锁或Next-Key

Next-Key Lock(临键锁)

Next-Key Lock 可以理解为一种特殊的间隙锁,也可以理解为一种特殊的算法,默认使用该锁
通过临键锁可以解决幻读的问题
每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据
需要强调的一点是,InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁

Insert Intention Locks(插入意向锁)

插入意向锁是一种特殊的间隙锁
该锁用以表示插入意向,当多个事务在同一区间(gap)插入位置不同的多条数据时,事务之间不需要互相等待

在InnoDB存储引擎中,通过使用Next-KeyLock算法来避免不可重复读的问题。在MySQL官方文档中将不可重复读的问题定义为PhantomProblem,即幻像问题。在Next-KeyLock算法下,对于索引的扫描,不仅是锁住扫描到的索引,而且还锁住这些索引覆盖的范围(gap)。因此在这个范围内的插入都是不允许的。这样就避免了另外的事务在这个范围内插入数据导致的不可重复读的问题。因此,InnoDB存储引擎的默认事务隔离级别是READREPEATABLE,采用Next-KeyLock算法,避免了不可重复读的现象。

发布了3 篇原创文章 · 获赞 5 · 访问量 882

猜你喜欢

转载自blog.csdn.net/Oooo_mumuxi/article/details/96194439