MySQL 里的几把锁

锁是实现事务隔离性的基础,通过锁事务之间能够相对独立互不影响。

MySQL 里有很多种锁,下面从不同角度进行分类和总结

基于属性分

  1. S 锁:持锁的事务允许读取一行

  2. X锁:持锁的事务允许更新、删除一行

同一数据行上, S锁和X锁会冲突:

图片

不同数据行上, S锁和X锁互不影响,能兼容:

图片

图片

排它锁之间也遵循同样的规则:

图片

图片

记住一个原则: innoDB 默认使用的行级别锁, 只要没有退化成表锁,这个规律就一直成立.

基于状态分

  1. 意向锁

意向锁是表级锁,用于指示事务稍后对表中的行需要哪种类型的锁(共享或排他)。

意向锁又分为:意向排它锁(IS),意向共享锁(IX).

其实上面用到的 select ... for update 就是 IX 锁, select .... for share 就是 IS 锁. 意向锁的存在意义在于在一些特定场景下,提高sql 引擎的效率,比如:

事务A:  update student set stu_name='张三1' where sno=0904031014;

事务B:  update student set stu_name='未知' ;

事务A 对学号是0904031014 这一行加了排他锁, 这个时候事物B需要对整个表加拍他锁.如果没有意向锁, 就需要逐行去检查是不是已经有事务加了锁(S 锁或 X 锁),效率非常低.意向锁相当于对整个表加了个状态: 已经有人对表里的一行加了一个排他锁了, 你们不能对整个表加共享锁或排它锁了.

基于粒度分

  1. 行锁

    InnoDB  默认使用的行级别锁,也支持表锁. 特殊情况下会退化为表锁.

    比如, 查询条件上没有建立索引(唯一或不唯一)时, 这个时候上锁的话锁住就是整张表.

    图片

  2. 表锁

    MyISAM 使用的是表级别锁.

  3. 记录锁

在唯一索引上加的锁,  是行锁的一种, 锁的是一行记录.即使表上没有索引, innodb 也会隐式创建一个聚簇索引来供记录锁使用.

     4. 间隙锁

在索引的一个范围加的锁.间隙可能包含一个索引、多个索引甚至是空.

间隙锁的目的非常单纯:就是“禁止”在间隙间修改或插入,换句话说间隙锁的作用是防止单个事务出现幻读. 只出现在 REPEATABLE_READ 隔离级别.

注意! 这里禁止并不是真正的禁止, 并不想排他锁一样阻塞其他事务的操作,而是你在持有间隙锁的本事务内看不到另一个事务做的任何修改操作,即使是已经提交的. 这也是从并发和性能角度考虑的.

只有持有间隙锁的事务提交后才能看到其他事务新提交的数据.


 

图片

共享间隙锁和排他间隙锁的功能都是一样的, 间隙锁间不会冲突,在同一个间隙上多个锁是允许的.

如果条件字段没有建立索引或者建立了非唯一索引, 该条件的前面也会加间隙锁!

图片

图片


 

5. Next-Key 锁

记录锁和间隙锁的结合, 锁住查询出来的记录,以及记录前的间隙锁, 是 Innodb 行锁的底层实现.

6. 自增锁

一种特殊的表级别锁,  多个事务向带有自增字段的表插入数据时, 必须等上个事务插入完成(返回自增数据)后才能继续插入.这样每个事务插入的数据具有连续的自增值.


如果觉得还不错的话,交个朋友, 原创不易,且看且珍惜~

posted on 2021-12-17 17:40  XuHe1  阅读(60)  评论(0编辑  收藏  举报