暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SQL语句到底加了哪些锁

二进制跳动 2020-07-09
78

开场白

什么是记录锁?

锁住记录,不过是锁住索引记录,不是真正的数据记录。

什么是间隙锁?

是在一个索引记录之间加的锁。保证某个间隙内的数据在锁定情况下不会发生任何变化。比如我mysql默认隔离级别下的可重复读(RR)

间隙锁有点抽象,我们来举个栗子:

以上数据为了解决幻读问题,更新的时候不只是对上述的五条数据增加行锁,还对于中间的取值范围增加了6间隙锁,(-∞,5](5,10](10,15](15,20](20,25](25,+supernum] (其中supernum是数据库维护的最大的值。为了保证间隙锁都是左开右闭原则。

当有如下事务A和事务B时,事务A会对数据库表增加(10,15]这个区间锁,这时insert id = 12 的数据的时候就会因为区间锁(10,15]而被锁住无法执行。

什么是临键锁?

记录锁与间隙锁的组合,它的封锁范围,既包含索引记录,又包含索引区间。

什么是快照读?

就是简单的select(不加类似于 for update之类的)

一、普通select

.在读未提交,读提交,可重复读这三种事务隔离级别下,普通的select是不加锁的,使用快照读。

二、加锁select

.select ... for update

.select ...  in share mode

在唯一索引上使用唯一查询条件,会使用记录锁,而不会封锁记录之间的间隙,即不会使用间隙锁和临键锁

有点抽象,举个例子:

tableA(id PK ,name)

有2条记录

wengyifei

zhangsan

SQL语句:

select * from tableA id = 1 for update 只会封锁记录,不会封锁区间


如果是其他的查询条件和索引条件,innodb会封锁扫描的索引范围,同时使用间隙锁和临键锁,防止在区间中插入。

三、update和delete

其实这边和上面说的select是类似的,在唯一索引上使用唯一查询使用记录锁,其余的使用间隙锁和临键锁。

update tableA set name = XXX where id = 1

也是只加记录锁


四、 insert

同样是写操作,insert有所不同,他会用排他锁封锁被插入的索引记录,而不会封锁记录之间的范围














文章转载自二进制跳动,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论