MySQL中的各种锁(行锁、间隙锁、临键锁等等LBCC)
目录
- 1.快照读和锁定读
- 1.1 一致性读 / 快照读
- 1.2 锁定读
- 1.2.1 共享锁和独占锁
- 1.2.2 锁定读的语句
- 1.2.2.1 Lock In Share Mode 对记录加S共享锁
- 1.2.2.2 For Update 对记录加X独占锁
- 2.表锁和行锁、X锁/S锁、IX锁、IS锁
- 2.1 意向锁 Intention Lock
- 2.2 InnoDB的表锁
- 3.InnoDB的行锁
- 3.1 Record Lock 记录锁
- 3.2 Gap Lock 间隙锁
- 3.3 Next-Key Lock 临键锁
- 3.4 Insert Intention Lock 插入意向锁(无实用)
- 4.锁的内存结构
1.快照读和锁定读
1.1 一致性读 / 快照读
事务的读取操作如果使用MVCC的方式读取就是快照读,它是一种无锁的读。所有的SELECT查询语句在可重复读、读已提交的级别下都是快照读。由于一致性读不会对记录进行加锁的操作,所以在并发环境下其它事务可以对表中的记录进行写操作。
1.2 锁定读
1.2.1 共享锁和独占锁
- `共享锁`:简称`S锁`,事务要读取一条记录时需要获取该记录的S锁。读读允许。- `独占锁/排它锁`:简称`X锁`,事务要改动一条记录需要获得该记录的X锁。读写、写读、写写都会阻塞。类似于Java中的ReentrantReadWriteLock。
1.2.2 锁定读的语句
锁定读
:读取记录信息前对记录进行加锁(S/X锁都行)的行为就叫锁定读
。
1.2.2.1 Lock In Share Mode 对记录加S共享锁
SELECT * FROM user WHERE id = 1 LOCK IN SHARE MODE
,这段语句就会对该记录进行加S锁,允许其它事务的读取,其它事务也可以继续加S锁,但是不允许其它事务加X锁,否则会阻塞,直到当前事务提交后释放了S锁,其它线程才能加X锁。
1.2.2.2 For Update 对记录加X独占锁
SELECT * FROM user WHERE id = 1 FOR UPDATE
,对该记录进行加X独占锁,其它事务要加S锁或者X锁都会被阻塞。生产环境严谨使用For Update。
2.表锁和行锁、X锁/S锁、IX锁、IS锁
MyISAM、MEMORY这些存储引擎他们只支持表锁且不支持事务。InnoDB支持表锁和行锁。
2.1 意向锁 Intention Lock
- `意向共享锁 IS锁`:当事务准备在某条记录上加S锁时,需要先在表上加IS锁。- `意向独占锁 IX锁`:当事务准备在某条记录上加X锁时,需要现在表上加IX锁。
2.2 InnoDB的表锁
一般情况InnoDB引擎在做CRUD时,不会对表进行加表级别的S锁或X锁的。但是对某个表执行了DDL语句就会阻塞其他的事务对表记录的修改。同样,一个正在对表记录进行修改的事务会将DDL操作阻塞。这个过程是通过在Service层的元数据锁 Metadata Lock
来完成的。
Auto-Inc锁
:主要用来对表进行插入记录,系统为记录赋予自增ID的作用,Insert语句执行时需要对表进行加Auto-Inc锁
来保证这个递增值的分配安全,和其它锁不一样的是,这个锁在Insert结束后就会立即释放。
InnoDB对自增ID的线程安全只采用Auto-Inc锁
的方式,有一个参数innodb_autoinc_lock_mode
来控制是否采用Auto-Inc锁方式,如果不采用这种方式就会采用一种轻量级锁的方式来保证自增ID的准确:简单来说就是为Insert语句修饰了自增属性的列获取一把锁然后分配ID,分配完成后立即释放,无需等到Insert语句结束才释放。
一般,对于确定Insert多少条记录的场景使用轻量级锁,对于不确定数量的Insert来说采用Auto-Inc锁的方式。
3.InnoDB的行锁
InnoDB的锁都是基于索引加锁的,如果修改语句没有使用索引,那么将升级为表锁。
3.1 Record Lock 记录锁
最普通的记录锁,普通记录锁是区分S锁和X锁的。
使用唯一性的索引进行等值查询且精准匹配到一条记录时,例如select * from student where id =2 for update;
就会将李四的记录锁定。
3.2 Gap Lock 间隙锁
间隙锁和临键锁的出现就是为了解决可重复读隔离级别下的幻读问题(快照读遇到当前读会有幻读问题)。间隙锁就是在目标记录行的上一条集合和当前目标记录之间的缝隙加一个锁。
仅在可重复读级别下生效。
使用等值查询/范围查询时,并且没有命中存在的记录,那么在索引对应区间生成间隙锁。例如select * from student where id =5 for update;
或select * from t where id > 2 and id < 7 for update;
就会将(2, 7)区间锁住。
因为InnoDB的锁时基于索引的,索引是根据索引字段进行排序的,所以通过间隙锁可以来阻止其它事务向该间隙插入记录。
3.3 Next-Key Lock 临键锁
临键锁是记录锁+间隙锁的组合形式,用来保护当前记录不被修改和这个间隙不予许插入。
临键锁适用于非唯一性索引,且仅在可重复读级别下生效。和间隙锁不同的是,临键锁是SQL命中了部分记录的场景,除了会锁定间隙外还会锁定命中记录的下一个区间,是一个左开右闭
的模式。
在可重复读级别下,MySQL默认就是使用的临键锁,当在非唯一索引下如果SQL没有命中记录则就是间隙锁,命中了记录就是临键锁。如果用唯一索引且SQL命中了记录,那么加的就是普通记录锁,否则就是间隙锁。
3.4 Insert Intention Lock 插入意向锁(无实用)
当A事务要插入一条记录时,要判断索引在这个位置区间是否被加了间隙锁或者临键锁,如果有的话,A事务就会阻塞,直到其它事务提交释放了锁为止。但是A事务处在等待过程中也需要在内存中生成一个锁结构,来表名A事务处于锁的等待过程中,这个锁就是插入意向锁。
4.锁的内存结构
行锁的n_bits:一个页面中存在多条记录,用不同的比特位来区分到底是哪一条记录加了锁。
MySQL中的各种锁(行锁、间隙锁、临键锁等等LBCC)相关推荐
- 在MySQL中删除重复的行
本文翻译自:Remove duplicate rows in MySQL I have a table with the following fields: 我有一个包含以下字段的表: id (Uni ...
- 周末杂谈:在MYSQL中,添加数据行后,使用右外连接查询所有课程的选修情况,要求列出课程编号、课程名称、选修人数,表中没有的课程列值为空的解决方法
周末杂谈:在MYSQL中,添加数据行后,使用右外连接查询所有课程的选修情况,要求列出课程编号.课程名称.选修人数,表中没有的课程列值为空的解决方法 实验前期准备 course表(课程表) 在其中: c ...
- oracle update 锁表还是锁行,for update造成的Oracle锁表与解锁
我遇到的情况: 当使用select语句查询表时,后面跟着for update , select * from table for update 当修改表中数据,但是没有commit就关掉PL/SQL, ...
- MySQL / B + 树算法在 mysql 中能存多少行数据?
在面试的时候,如果问到了 B + 树这个东西,或者问到了 MySQL 索引的底层实现,也希望大家能够进一步的发挥,和面试官探讨一下,为什么 B+ 树一般都是 3 层左右,为什么 3 层的 B + 树可 ...
- B+树算法在mysql中能存多少行数据?
在面试的时候,如果问到了B+树这个东西,或者问到了MySQL索引的底层实现,也希望大家能够进一步的发挥,和面试官探讨一下,为什么B+树一般都是3层左右,为什么3层的B+树可以存放2千万的数据,这个到底 ...
- mysql中如何取消1000行的查询限制?
在使用数据库时,常常会有需要使用select语句查询表的情况.当使用select * 进行查询时,mysql中默认查询表的前1000行,也就是说如果表中的数据库超过了1000行,查询结果就会显示不完整 ...
- mysql中表格 列变行_MySQL数据透视表的列数据作为行
我正在努力寻找解决此MySQL问题的方法.我似乎无法理解该怎么做.我有下表. Question table +----+-------------+ | id | question | +----+- ...
- mysql 获取更新id,如何获取MySQL中最后更新的行的ID?
How do I get the ID of the last updated row in MySQL using PHP? 解决方案 I've found an answer to this pr ...
- 【Java面试题】6年开发去A里面试P6竟被Mysql难住了,说一下你对行锁、临键锁、间隙锁的理解
一个工作了6年的程序员,最近去阿里面试p6这个岗位. 面试之前信心满满的和我说,这次一定要拿下 35k月薪的offer. 然后,在第一面的时候,被Mysql里面的一个问题难住了. 大家好,我是Mic, ...
最新文章
- 【斯坦福大学】可信任机器学习课程,附课件
- SAP PP 启用了MRP Area之后MMBE有什么变化?
- Azure SQL Database (19) Stretch Database 概览
- 8.6M超轻量中英文OCR模型开源,训练部署一条龙 | Demo在线可玩
- 类与接口(五)java多态、方法重写、隐藏
- 【图论】【高精】产生数(ssl 1021/ luogu 1037)
- 阿里AI界的新伙伴,1秒钟自动生成20000条文案
- jQuery 图片裁剪插件 Jcrop
- 电脑ping_Windows系统——ping打开教程
- Pygal简介、画廊--各种图形绘图代码
- Js中Currying的应用
- 一文教你分清持续集成,持续交付,持续部署!
- Codeforces Round #296 (Div. 2) C. Glass Carving [ set+multiset ]
- liunx 命令 之 mkdir 与 touch
- sendmail配置
- html标签b规定粗体文本
- 几种炫酷的Web特效
- 阿里软件测试工程师手把手教学——APP蓝牙连接测试
- 微信小程序实现当前页面多个视频文件只能播放一个视频,其他视频暂停,点击当前暂停当前
- 冰蝎Behinder_v4.0
热门文章
- 2021考研英语大作文写作必备15个话题
- 哈理工第六届程序设计大赛 G 逃脱(BFS)
- 使用cloudcompare使xy轴的值反过来
- 关于 英文的 金额转换
- SpringBoot配置多个RabbitMq
- vue 引入图片出现错误 Cannot find module ‘./XXX.jpg‘e
- am服务器查找信息,am服务器
- 论文解读:《利用注意力机制提高DNA的N6-甲基腺嘌呤位点的鉴定》
- 英国《金融时报》:全力加码早期投资,红杉中国在下一盘怎样的棋?...
- CRM系统的灵活运用