网站首页 > 教程文章 正文
在MySQL InnoDB中有7种锁:
- 共享锁(S锁)、排他锁(X锁)
- 意向锁(Intention Locks)
- 记录锁(Record Locks)
- 间隙锁(Gap Locks)
- 临键锁(Next-Key Locks)
- 插入意向锁(Insert Intention Locks)
- 自增锁(Auto-inc Locks)
这7种锁,锁的范围、锁的类型都不同
按锁的粒度来分,分为表锁、行锁、范围锁(gap间隙锁)
按锁的类型来分,分为共享锁、排他锁、意向锁
锁的粒度
- 表锁:表级别是对操作的整张表加锁,锁定颗粒度大,资源消耗小,不会出现死锁,但并发度低
- 行锁:MyISAM引擎只支持表锁,InnoDB支持行锁级别,锁粒度小并发高,持有锁资源越多,消耗也多,可能出现死锁。
- 范围锁:范围锁是锁住一个范围,锁记录之前的范围,是一个开区间,目的是避免另一个事务在这个区间上插入新记录
锁的类型
- 共享锁(S)也叫是读锁,读和读之间允许并发,读和写之间不能并发;
- 排他锁(X)是写锁,读和写之间不能并发,写和写之间也不能并发。表和行两个粒度均有共享锁、排他锁类型。
- 意向锁是表锁的一种,为了解决表锁与行锁冲突判断效率问题产生的。
试想下面场景,有两个事务T1、T2
T1: 锁住表中的一行,只能读不能写(行级读锁)
T2:申请整个表的写锁(表级写锁)
如果T2申请成功,则能任意修改表中的一行,但这与T1持有的行锁是冲突的。所以数据库要识别这种冲突,让T2的申请的锁被阻塞,直到T1释放行锁。
怎样识别出这种冲突,最简单办法是遍历每一行判断是否被行锁锁住,这种办法效率很低。
innodb想到使用意向锁来解决这个问题,T1在加行级锁之前,给表申请加上一个意向共享锁(IS)。如果发现表上有意向共享锁,说明表中行被共享行锁锁住了,因此T2申请表写锁会被阻塞。
锁的兼容性分析如下表:
横轴表示已持有的锁,纵轴表示尝试获取的锁。1表示成功(即兼容,正常进行下一步操作),0表示失败(即冲突,阻塞住当前操作)
兼容性 | IX | IS | X | S |
IX | 1 | 1 | 0 | 0 |
IS | 1 | 1 | 0 | 1 |
X | 0 | 0 | 0 | 0 |
S | 0 | 1 | 0 | 1 |
总的来说,排他锁和共享锁、意向锁会发生冲突并导致阻塞,而意向锁之间不会冲突。共享锁和共享意向锁则不会发生冲突。
如何加锁:
- 普通select...查询(不加锁)
- 普通insert、update、delete...(开启事务,隐式加写锁)
- select..lock in share mode(加读锁)
- select ... for update (加写锁)
解锁:
提交或回滚事务、kill阻塞进程
锁的类型分类
记录锁是行锁,仅仅是锁住一行,会阻塞其他事务对其插入、更新、删除
select id from t where id = 1 for update
自增锁是一种表级别的锁,专门针对自动递增的列,是为了防止其他事务在两次连续的insert中间插入一条记录,因为id自增列取值是连续的,如果不加AI锁,第一次insert值是5,第二次insert值可能不是6,中间被插入其他记录,值变成7。
对应事务来说很奇怪,明明连续插入了两条数据,自增列却不是连续递增。
start transaction
insert t1 values(a.b,c);
insert t1 values(a,b,c);
select a from t1 where xxx
commit
间隙锁(gap lock)是锁住一个范围,不包含记录本身,目的是避免另一个事务在这个范围内插入新记录。
临键锁(next-key lock)是间隙锁与记录锁组合,是在某条记录以及这条记录前面间隙上加锁。
插入意向锁(insert intension lock)是专门针对插入操作,目的是为了提高并发插入能力。多个事务申请意向锁时,只要不是插入在范围内相同位置不需要阻塞等待,在同一索引、同一范围区间内可以并发插入。
普通gap lock不允许在(上一条记录,本记录)范围内插入数据
插入意向锁允许在(上一条记录,本记录)范围内插入数据
是否加gap锁和事务隔离级别密切相关,如果事务的隔离级别是RC,允许幻读,则不需要锁范围。
gap锁往往是针对非唯一索引,如果通过主键索引、或者非主键索引,可以明确地定位到哪一条或者哪几条记录的修改,则不需要锁范围。
猜你喜欢
- 2025-07-01 结合隔离级别RR和RC来详细讲解下MVCC和LBCC
- 2025-07-01 Java锁最全详解(独享锁+共享锁+公平锁+非公平锁+乐观锁+悲观锁)
- 2025-07-01 美团面试:MySQL悲观锁是什么?谈谈底层实现原理?
- 2025-07-01 什么是悲观锁,什么是乐观锁,有什么区别
- 2025-07-01 MySQL进行行级锁的?一会next-key锁,一会间隙锁,一会记录锁?
- 2025-07-01 MySQL8行级锁(mysql如何加行级锁)
- 2025-07-01 二阶段提交的 prepare 阶段,binlog 和 InnoDB 各自会有哪些动作?
- 2025-07-01 看懂这篇文章,你就懂了数据库死锁产生的场景和解决方法
- 2025-07-01 深入理解MySQL锁机制原理(mysql锁的作用)
- 2025-07-01 一文由浅入深带你完全掌握MySQL的锁机制原理与应用
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- mybatis plus page (35)
- vue @scroll (38)
- 堆栈区别 (33)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)
- redis aof rdb 区别 (33)
- 302跳转 (33)
- http method (35)
- js array splice (33)