当前位置:   article > 正文

mysql锁(共享锁、排他锁、意向锁、间隙锁、死锁)_不需要加意向锁

不需要加意向锁

数据库必知必会:锁和事务

数据库锁-概览图

按使用方式

  • 乐观锁:很乐观,每次读写数据时都认为别人不会修改这条数据,因此不上锁(不使用数据库的锁机制),通过版本控制的方式来避免并发事务间的数据冲突。乐观锁比较适合读操作很多的高并发应用,可以提高吞吐量。
  • 悲观锁:很悲观,每次读写数据都担心别人修改这条数据,所以每次都上锁(使用数据库的锁机制)。

乐观锁:在数据表增加一个 “version” 字段,数据行每更新一次,其version值加一。当需要提交更新时,对比数据行的当前版本号与同一事务中第一次读操作取出来的版本号,一致则更新,不一致则说明数据已过期,不更新,并且返回错误给用户,交由用户判断。

按粒度

  • 表级锁:将整个表锁住,锁定粒度大,开销小,适合并发度较低的情况。
  • 行级锁:只锁住某个行,锁定粒度小,开销大,适合并发度较高的情况。

表级锁和行级锁中都有以下这两种锁:

  • 共享锁(读锁):其他事务可以读,不可以写。
  • 排他锁(写锁):其他事务不可以读也不可以写。

其他

意向锁

二者冲突。InnoDB为了让行级锁与表级锁共存,又加入了意向锁(粒度属于表锁)。当一个事务要对某一行加行级锁时,它需要先给表加上意向锁(加共享锁就要加意向共享锁,加排他锁就要加意向排他锁)。原因如下:

  • 不加意向锁:事务A对某一行加上共享锁后(事务A要读这一行),事务B想要对这个表加上排他锁(事务B要写这个表)。由于排他锁不允许其他事务读或者写这个表,因此事务B需要检查每一行是否有共享锁或者排他锁,而逐行检查带来非常大的开销。

  • 加意向锁:事务A想对这个表加上意向共享锁,然后对目标行加上共享锁,随后事务B想要对这个表加上排他锁,此时事务B只需要检查表上是否有意向共享锁或者意向排他锁即可,如果有其一就不可以加锁,需要等待意向锁释放,如果都没有就可以加锁。

意向锁是InnoDB自动加的,不需用户干预。

间隙锁

间隙锁(Next-Key锁)是指当我们用范围条件检索数据且申请锁时,不仅会给范围条件内已有的数据记录加锁,而且还给那些处于范围条件内但不存在的数据记录(间隙)加锁,目的是防止幻读。如果不使用间隙锁,则执行上述事务时,另一个事务插入新的数据记录且处于范围条件内,就会导致幻读。而加上间隙锁则可以阻止后者在此范围内插入新数据。(春招面试题,当时我没有看过这个锁,只答成了锁表,失败)但是如果应用场景下有大量插入操作时,需要尽量避免使用间隙锁,否则会阻塞大量的插入请求。

死锁

可以认为数据记录或者数据表是一种资源,死锁的一个典型场景:事务A先申请数据行1的共享锁,然后申请数据行2的排他锁。事务B先申请数据行2的共享锁,后申请数据行1的排他锁。结果事务A和B申请完共享锁后,申请排他锁的请求都被对方block住了,导致死锁。(表级锁也有这种情况)

数据库自动加锁

程序员一般不需要关心表锁

  • 在MyISAM存储引擎中,当执行SQL语句的时候自动加表锁。
  • 在InnoDB存储引擎中,如果没有使用索引,表锁也是自动加的。

现在大多数情况都是使用MySQL的InnoDB引擎,InnoDB支持行锁

  • 没有使用索引:使用表锁。
  • 使用了索引:查询语句仍使用表锁而不是行锁;只有使用了索引的更新语句才使用行锁。

注意:InnoDB行锁是通过给索引上的索引节点加锁来实现的,只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁,即where 后面的字段里必须包含有索引的字段(主键索引、辅助索引),然后把行级锁加载索引节点上。

一般情况下数据库自动加的锁是够用的。然而当我们要用到数据库事务时,有可能需要手动加锁确保事务的正确执行。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号