MySQL-InnoDB 锁的基本类型

路。

Mysql官网对锁的介绍

锁的基本模式——共享锁

第一个行级别的锁就是我们在官网看到的 Shared Locks (共享锁),我们获取了一行数据的读锁以后,可以用来读取数据,所以它也叫做读锁。而且多个事务可以共享一把读锁。那怎么给一行数据加上读锁呢?

我们可以用 select lock in share mode;的方式手工加上一把读锁。

释放锁有两种方式,只要事务结束,锁就会自动事务,包括提交事务和结束事务。

锁的基本模式——排它锁

第二个行级别的锁叫做 Exclusive Locks(排它锁),它是用来操作数据的,所以又叫做写锁。只要一个事务获取了一行数据的排它锁,其他的事务就不能再获取这一行数据的共享锁和排它锁。

排它锁的加锁方式有两种,第一种是自动加排他锁,可能是同学们没有注意到的:

我们在操作数据的时候,包括增删改,都会默认加上一个排它锁。

还有一种是手工加锁,我们用一个 FOR UPDATE 给一行数据加上一个排它锁,这个无论是在我们的代码里面还是操作数据的工具里面,都比较常用。

释放锁的方式跟前面是一样的。

锁的基本模式——意向锁

意向锁是由数据库自己维护的。

也就是说,当我们给一行数据加上共享锁之前,会自动在这张表上面加一个意向共享锁。

当我们给一行数据加上排他锁之前,会自动在这张表上面加一个意向排他锁。

反过来说:

如果一张表上面至少有一个意向共享锁,说明有其他的事务给其中的某些数据行加上了共享锁。

锁的算法

t2 这张表 id 有一个主键索引。我们插入了 4 行数据,主键 id 分别是 1、4、7、10。

我们这里的划分标准是主键 id。

这些数据库里面存在的主键值,我们把它叫做 Record,记录,那么这里我们就有 4 个 Record。

根据主键,这些存在的 Record 隔开的数据不存在的区间,我们把它叫做 Gap,间隙,它是一个左开右开的区间。

假设我们有 N 个 Record,那么所有的数据会被划分成多少个 Gap 区间?答案是 N+1,就像我们把一条绳子砍 N 刀,它最后肯定是变成 N+1 段。

最后一个,间隙(Gap)连同它左边的记录(Record),我们把它叫做临键的区间,它是一个左开右闭的区间。

如果主键索引不是整型,是字符怎么办呢?字符可以排序吗? 基于 ASCII 码

记录锁

第一种情况,当我们对于唯一性的索引(包括唯一索引和主键索引)使用等值查询,精准匹配到一

条记录的时候,这个时候使用的就是记录锁。

比如 where id = 1 4 7 10 。

间隙锁

第二种情况,当我们查询的记录不存在,无论是用等值查询还是范围查询的时候,它使用的都是间隙锁。

临键锁

第三种情况,当我们使用了范围查询,不仅仅命中了 Record 记录,还包含了 Gap 间隙,在这种情况下我们使用的就是临键锁,它是 MySQL 里面默认的行锁算法,相当于记录锁加上间隙锁。

比如我们使用>5 <9 , 它包含了不存在的区间,也包含了一个 Record 7。

锁住最后一个 key 的下一个左开右闭的区间。

select * from t2 where id >5 and id <=7 for update; 锁住(4,7]和(7,10]

select * from t2 where id >8 and id <=10 for update; 锁住 (7,10],(10,+∞)

总结:为什么要锁住下一个左开右闭的区间?——就是为了解决幻读的问题。

猜你喜欢

转载自blog.csdn.net/ahuangqingfeng/article/details/124470858