数据库系列-MySQL系列

详解mysql中的各类锁

2021-01-28  本文已影响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.死锁

上一篇下一篇

猜你喜欢

热点阅读