MySQL锁-详解

MySQL里的锁

1、加锁的目的是什么

对数据加锁是为了解决事务的隔离性问题,让事务之间相互不影响,每个事务进行操作的时候都必须先对数据加上一把锁,防止其他事务同时操作数据。

事务的隔离性:隔离性是指两个事务的执行是独立隔离开的,事务之间不会相互影响,多个事务操作一个对象时会以串行等待的方式保证事务相互之间是隔离的。(并行执行的两个事务A和B,事务A的执行不会影响事务B,事务B的执行不会影响事务A的执行)


2、锁是基于什么实现的

数据库里面的锁是基于索引实现的,在Innodb中我们的锁都是作用在索引上面的,当我们的SQL命中索引时,那么锁住的就是命中条件内的索引节点(行锁),如果没有命中索引的话,那么我们锁的就是整个索引树(表锁),如下图锁住的是整棵树还是某几个节点,完全取决于你的条件是否有命中到对应的索引节点。


3、锁的分类

  • 基于锁的属性分类:共享锁、排他锁
  • 基于锁的粒度分类:表锁、行锁(记录锁、间隙锁、临键锁)
  • 基于锁的状态分类:意向共享锁、意向排他锁

3.1、属性锁

共享锁(Share Lock)

共享锁又称读锁,简称S锁。当一个事务对数据加上读锁之后,其他事务只能对该数据加读锁,而无法对数据加写锁,直到所有的读锁释放之后其他事务才能对其加写锁。加了共享锁之后,无法再加排他锁,这也就可以避免读取数据的时候会被其他事务修改,从而导致不可重复读问题

排他锁(eXclusive Lock)

排他锁又称写锁,简称X锁;当一个事务对数据加上写锁之后,其他事务将不能再为数据加任何锁,直到该锁释放之后,其他事务才能对数据加锁。加了排他锁后,其它事务就无法再对数据进行读取和修改,所以也就避免了脏写和脏读问题。

ps:
1、脏写问题:事务A和事务B同时写数据,事务A先对数据进行修改,未提交。此时事务B对数据进行了修改并提交事务。然后事务A发生错误进行回滚,将事务B的操作撤销。举例:两个人同时对同一账户存款,账户原有1000元,A存入500元,未提交。B存入500元并提交事务,存款变成2000元。这时A事务进行回滚,导致账户余额回到A事务开始时的状态,将已提交事务B的操作也撤销掉,余额变成1000元。

加上排他锁可以避免脏写问题:事务A在写数据时,加上排他锁,这个排他锁只有事务A提交或者回滚才会释放。其他对该数据进行操作的事务就会阻塞,等到事务A操作完成才能获取锁进行操作。

2、脏读问题:事务读取到其他事务已经修改但还没有提交的数据。举个例子:假设A与B共用一张银行卡,银行卡内余额为1000,此时B取款1000元,但未提交事务。A读取到账户余额为0,然后B事务回滚,余额恢复为1000元。此时A存款500元,余额=0+500,A提交事务,最后账户余额为500元。

加上排他锁可以避免脏读问题:事务B在写数据时,加上排他锁,这个排他锁只有事务B提交或者回滚才会释放,其他对该数据进行操作的事务就会阻塞,也就不能读取到未提交的数据了。


3.2、粒度锁

表锁

表锁是指上锁的时候锁住的是整张表,当下一个事务访问该表的时候,必须等前一个事务释放了锁才能对标进行访问。

特点:粒度大,加锁简单,容易冲突

行锁

行锁是所有行级别锁的一个统称,记录锁、间隙锁、临键锁都是属于行锁,行锁是指加锁的时候锁住的是标的某一行或多行记录,多个事务访问同一张表时,只有被锁住的记录不能访问,其他记录可正常访问。

特点:粒度小,加锁比表锁麻烦,不同意冲突,相比于表锁支持的并发要高。

记录锁(Record Lock)

记录锁属于行锁的一种,记录锁的范围只是表中的某一条记录,记录锁是说事务在加锁后锁住的只是表的某一条记录。

触发条件:精准条件命中,并且命中索引

例如:update user_info set name=‘张三’ where id=1,这里的id是索引

记录锁的作用:加了记录锁之后数据可以避免数据在查询的时候被修改的不可重复读问题,也避免了在修改事务未提交前被其他事务读取的脏读问题

ps:
1、记录锁如何解决脏读问题:事务在写数据的时候,对数据加记录锁,直到事务回滚或提交才释放。这时其他事务无法读取该数据,也就不会发生脏读。

2、不可重复读问题:事务A查询数据,然后事务B修改该数据并提交事务,事务A再次查询数据,这次查询到的数据与之前查询到的数据不同。这就是重复读问题。举个例子:A和B通用一张银行卡,银行卡内余额为1000元,A查询银行卡余额为1000元,然后事务B取款1000元,并提交事务,A再次查询,发现余额为0元。

记录锁如何解决不可重复读问题:事务A读取数据,并对数据加上记录锁,该记录锁直到事务A提交或回滚才释放。此时其他事务无法对数据进行修改,因此事务A前后两次读取到的数据一定是相同的。

间隙锁(Gap Lock)

间隙锁属于行锁的一种,间隙锁是在事务加锁后其锁住的是表记录的某一个区间,当表的相邻ID之间出现空隙则会形成一个区间。

触发条件:主键或唯一索引作为条件等值查询没有命中记录,或者在范围查询没有命中记录时(REPEATABLE_READ隔离级别)

间隙锁作用:防止幻读问题

ps:
1、幻读问题:事务A查询id=2的记录,但是没有查询到。此时事务B插入一条id=2的记录,并提交事务。事务A插入id=2的记录,结果是插入失败,因为id=2的记录已经存在。但是事务A再次查询id=2的事务,仍然查询不到(已经解决了不可重复读:保证一个事务中前后查询结果一样)。

间隙锁如何解决幻读:在事务A查询id=2的记录,没有查询到,会在id=2这个间隙添加间隙锁,直到事务结束后释放,此时事务B想要插入id=2的数据就必须等到事务A回滚或结束释放id=2的间隙锁。这样也就不会出现幻读问题。

临键锁(Next-Key Lock)

临键锁也属于行锁的一种。它是记录锁和间隙锁的组合,临键锁会把查询出来的记录锁住,同时也会把该范围查询内的所有间隙空间锁住。

临键锁的作用:结合记录锁和间隙锁的特性,临键锁避免了在范围查询时出现脏读、重复读、幻读问题。加了临键锁,在范围区域内的数据不允许被修改和插入。


3.3、状态锁

这点可以参考之前的黑马程序员的阅读笔记

【MySQL锁】-黑马程序员视频观看笔记


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值