详解mysql中的各类锁

作者: 刘辉丶 | 来源:发表于2021-01-28 11:14 被阅读0次

一、存储引擎中锁的区别

在介绍锁之前,我们先来了解下mysql的存储引擎。我们常用的存储引擎一般有两种,MyISAM和InnoDB,其中InnoDB最常用。至于两种存储引擎的特性我们就不在这里展开了,我们来看一下两种存储引擎里的锁有什么不同呢?

1、MyISAM

MyISAM里是表锁的形式。所谓表锁就是对整张表进行加锁,优点是它的开销小,加锁快;锁定粒度大,并且不会发生死锁。缺点是因为是对整张表进行加锁的,所以发生锁冲突的概率也是最高的,并发度也比较低。

表锁又分为共享锁(读锁)排它锁(写锁);共享锁又称为读锁,也就是说针对同一个表操作,如果两个请求都是读请求的情况下,是不会互相影响的。但是如果其中一个是写操作的话,则会阻塞其他的写操作或读操作,直到锁释放为止。

默认情况下,写锁比读锁具有更高的优先级:当一个锁释放时,这个锁会优先给写锁队列中等候的获取锁请求,然后再给读锁队列中等候的获取锁请求。这也正是 MyISAM 表不太适合于有大量更新操作和查询操作应用的原因,因为,大量的更新操作会造成查询操作很难获得读锁,从而可能永远阻塞。

2.表级锁加锁方式

了解了表锁后,我们来看一下MyISAM是如何进行加锁的呢?其实MyISAM 在执行查询语句(SELECT)前,会自动给涉及的表加读锁,在执行写操作
(UPDATE、DELETE、INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户干预。当然,mysql也提供了LOCK TABLE 命令给 MyISAM 表显式加锁。在自动加锁的情况下,MyISAM 总是一次获得 SQL 语句所需要的全部锁,这也正是 MyISAM 表不会出现死锁的原因。

3.InnoDB

说完了MyISAM,我们来说下InnoDB,InnoDB中既有表锁也有行锁。其中行锁也是分为共享锁(读锁)排它锁(写锁),只不过不同于表锁的是行锁的锁是作用于行数据,而不是作用于整张表。除此之外InnoDB还有意向共享锁意向排它锁,意向锁也是表级锁,为什么会有这两种锁呢?

由于表锁和行锁虽然锁定范围不同,但是会相互冲突。所以当你要加表锁时,势必要先遍历该表的所有记录,判断是否加有排他锁。这种遍历检查的方式显然是一种低效的方式,MySQL 引入了意向锁,来检测表锁和行锁的冲突。

当事务要在记录上加上读锁或写锁时,要首先在表上加上意向锁。这样判断表中是否有记录加锁就很简单了,只要看下表上是否有意向锁就行了。意向共享锁可以同时并存多个,但是意向排他锁同时只能有一个存在。意向锁是InnoDB自动加的,不需要用户干预。

4.行级锁加锁方式

共享锁:

对于普通的查询语句是不会加锁的,列如 select * from user;

对于有查询条件的语句,如果查询条件中有索引列,则使用行锁,如果查询条件非索引列,则使用表锁。

显示加锁:SELECT * FROM table_name WHERE ... LOCK IN SHARE MODE

排它锁:

对于UPDATE、DELETE和INSERT语句,InnoDB会自动给涉及数据集加排他锁;
显示加锁:SELECT * FROM table_name WHERE ... FOR UPDATE

5.间隙锁

间隙锁产生的原因是因为Query执行过程中通过范围查找的话,它会锁定整个范围内所有的索引键值,即使这个键值并不存在。
例:假如user表中只有101条记录,其id的值分别是 1,2,…,100,101,下面的SQL:

mysql> select * from user where id > 100 for update;

是一个范围条件的检索,InnoDB不仅会对符合条件的id值为101的记录加锁,也会对id大于101(这些记录并不存在)的“间隙”加锁。当然间隙锁的好处主要是防止防幻读。此时如果还能插入一条102的数据,则会导致幻读。缺点是在插入频繁的操作使用不当会造成大量阻塞,所以我们要尽量避免这种范围条件。

6.死锁

  • 死锁产生:
    • 死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。
    • 当事务试图以不同的顺序锁定资源时,就可能产生死锁。多个事务同时锁定同一个资源时也可能会产生死锁。
    • 锁的行为和顺序和存储引擎相关。以同样的顺序执行语句,有些存储引擎会产生死锁有些不会——死锁有双重原因:真正的数据冲突;存储引擎的实现方式。
  • 检测死锁:数据库系统实现了各种死锁检测和死锁超时的机制。InnoDB存储引擎能检测到死锁的循环依赖并立即返回一个错误。
  • 死锁恢复:死锁发生以后,只有部分或完全回滚其中一个事务,才能打破死锁,InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。所以事务型应用程序在设计时必须考虑如何处理死锁,多数情况下只需要重新执行因死锁回滚的事务即可。
  • 外部锁的死锁检测:发生死锁后,InnoDB 一般都能自动检测到,并使一个事务释放锁并回退,另一个事务获得锁,继续完成事务。但在涉及外部锁,或涉及表锁的情况下,InnoDB 并不能完全自动检测到死锁, 这需要通过设置锁等待超时参数 innodb_lock_wait_timeout 来解决
  • 死锁影响性能:死锁会影响性能而不是会产生严重错误,因为InnoDB会自动检测死锁状况并回滚其中一个受影响的事务。在高并发系统上,当许多线程等待同一个锁时,死锁检测可能导致速度变慢。 有时当发生死锁时,禁用死锁检测(使用innodb_deadlock_detect配置选项)可能会更有效,这时可以依赖innodb_lock_wait_timeout设置进行事务回滚。
  • 死锁预防:可以尽量在不同的事物中指定操作顺序,达到事物顺序一致,来避免多个事物同一资源的互相占用

相关文章

  • 详解mysql中的各类锁

    一、存储引擎中锁的区别 在介绍锁之前,我们先来了解下mysql的存储引擎。我们常用的存储引擎一般有两种,MyISA...

  • 锁-2

    一.mysql中行级锁中的共享锁与排他锁详解:https://www.cnblogs.com/mr-wuxians...

  • MySQL中锁详解

    原文地址:http://blog.csdn.net/mysteryhaohao/article/details/5...

  • Mysql 锁详解

    Mysql 锁详解一、前言二、MyISAM2.1 MyISAM表锁2.2 查询表级锁争用情况2.3 MySQL表级...

  • MySQL记录锁、间隙锁、临键锁(Next-Key Locks)

    MySQL记录锁、间隙锁、临键锁(Next-Key Locks)详解[https://www.jianshu.co...

  • 锁-0

    一.事务是通过锁来绑定多条执行语句的 二.mysql 锁粒度是什么?详解:https://zhidao.baidu...

  • MySQL 锁详解

    InnoDB 锁 数据库使用锁是为了支持更好的并发,提供数据的完整性和一致性。InnoDB是一个支持行锁的存储引擎...

  • MySQL锁详解

    一、概述 数据库锁定机制简单来说,就是数据库为了保证数据的一致性,而使各种共享资源在被并发访问变得有序所设计的一种...

  • mysql锁详解

    1. mysql锁知多少 我们进行insert,update,delete,select会加锁吗,如果加锁,加锁步...

  • MySQL锁详解

    Mysql****锁机制 锁概述 锁分类 MySql锁 目的了解锁的用途了解锁的危害根据锁的一个概述进一步了解优化...

网友评论

    本文标题:详解mysql中的各类锁

    本文链接:https://www.haomeiwen.com/subject/hiyttltx.html