表级锁、行级锁、页级锁
表级锁定
,行级锁定
和页级锁定
。表级锁
行级锁
使用行级锁定的主要是InnoDB存储引擎
页级锁
总结
表级锁
:开销小,加锁快;不会出现死锁;锁定粒度大,发生锁冲突的概率最高,并发度最低;行级锁
:开销大,加锁慢;会出现死锁;锁定粒度最小,发生锁冲突的概率最低,并发度也最高;页面锁
:开销和加锁时间界于表锁和行锁之间;会出现死锁;锁定粒度界于表锁和行锁之间,并发度一般。共享锁、排它锁
读锁会阻塞写(X),但是不会堵塞读(S)。而写锁则会把读(S)和写(X)都堵塞
-- 加共享锁(S)
select * from table_name where ...
lock in share mode
-- 加排它锁(X)
select * from table_name where ...for update
记录锁(Record Locks)
SELECT * FROM `test` WHERE `id`=1
FOR UPDATE;
-
id 列必须为唯一索引列或主键列,否则上述语句加的锁就会变成临键锁(有关临键锁下面会讲)。
-
同时查询语句必须为精准匹配(=),不能为 >、<、like等,否则也会退化成临键锁。
-- id 列为主键列或唯一索引列
UPDATE SET age = 50 WHERE id = 1;
记录锁也是排它(X)锁,所以会阻塞其他事务对其插入、更新、删除。
间隙锁(Gap Locks)
幻读问题
时引入的锁机制。间隙锁是innodb中行锁的一种。SELECT * FROM emp WHERE empid > 100
FOR UPDATE
临键锁(Next-Key Locks)
幻读
的问题。每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。需要强调的一点是,InnoDB 中行级锁是基于索引实现的,临键锁只与非唯一索引列有关,在唯一索引列(包括主键列)上不存在临键锁
(-∞, 10],
(10, 24],
(24, 32],
(32, 45],
(45, +∞],
在事务 A 中执行如下命令:
-- 根据非唯一索引列 UPDATE 某条记录
UPDATE table SET name = Vladimir WHERE age = 24;
-- 或根据非唯一索引列 锁住某条记录
SELECT * FROM table WHERE age = 24FOR UPDATE
;
INSERT INTO table VALUES(100, 26, 'tianqi');
总结
-
InnoDB 中的行锁的实现依赖于索引,一旦某个加锁操作没有使用到索引,那么该锁就会退化为
表锁
。 -
记录锁存在于包括主键索引在内的唯一索引中,锁定单条索引记录。
-
间隙锁存在于非唯一索引中,锁定开区间范围内的一段间隔,它是基于临键锁实现的。
-
临键锁存在于非唯一索引中,该类型的每条记录的索引上都存在这种锁,它是一种特殊的间隙锁,锁定一段左开右闭的索引区间。
意向锁
意向锁也分为意向共享锁(IS) 和 意向排他锁(IX)
-
意向共享(IS)锁:事务有意向对表中的某些行加共享锁(S锁)
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
SELECT column FROM table ...LOCK IN SHARE MODE
;
-
意向排他(IX)锁:事务有意向对表中的某些行加排他锁(X锁)
-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
SELECT column FROM table ...FOR UPDATE
;
-
意向共享锁(IS)和 意向排他锁(IX)都是表锁。
-
意向锁是一种 不与行级锁冲突的表级锁,这一点非常重要。
-
意向锁是 InnoDB 自动加的, 不需用户干预。
-
意向锁是在 InnoDB 下存在的内部锁,对于MyISAM 而言 没有意向锁之说。
我们可以理解 意向锁 存在的目的就是 为了让InnoDB 中的行锁和表锁更高效的共存。
SELECT * FROM users WHERE id = 6
FOR UPDATE
;
LOCK TABLES users READ;
-
当前没有其他事务持有 users 表的排他锁。
-
当前没有其他事务持有 users 表中任意一行的排他锁 。
表级
排他(X)/共享(X)锁。注意
这里的排他(X)/共享(S)锁指的都是表锁!意向锁不会与行级的共享/排他锁互斥! 插入意向锁
INSERT INTO users SELECT 4, 'Bill', 15;
INSERT INTO users SELECT 5, 'Louis', 16;
-
插入意向锁是一种特殊的间隙锁 —— 间隙锁可以锁定开区间内的部分记录。
-
插入意向锁之间互不排斥,所以即使多个事务在同一区间插入多条记录,只要记录本身(主键、唯一索引)不冲突,那么事务之间就不会出现冲突等待。
虽然插入意向锁中含有意向锁三个字,但是它并不属于意向锁而属于间隙锁,因为意向锁是表锁而插入意向锁是行锁。
2、事务 A 不会阻塞事务 B。
-
id 为 4 的记录行的记录锁。
-
age 区间在(10,15] 的间隙锁。
-
age 区间在(15,20] 的间隙锁。
INSERT INTO users SELECT 5, 'Louis', 16;
总结
-
InnoDB在RR的事务隔离级别下,使用插入意向锁来控制和解决并发插入。
-
插入意向锁是一种特殊的间隙锁。
-
插入意向锁在锁定区间相同但记录行本身不冲突的情况下互不排斥。
原文始发于微信公众号(后端元宇宙):一文详解MySQL的锁机制
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/28139.html