加入收藏 | 设为首页 | 会员中心 | 我要投稿 常州站长网 (https://www.0519zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长学院 > MySql教程 > 正文

MySQL的又一神器-锁,MySQL面试必备

发布时间:2019-10-25 18:35:55 所属栏目:MySql教程 来源:欧阳思海
导读:副标题#e# 1 什么是锁 1.1 锁的概述 在生活中锁的例子多的不能再多了,从古老的简单的门锁,到密码锁,再到现在的指纹解锁,人脸识别锁,这都是锁的鲜明的例子,所以,我们理解锁应该是非常简单的。 再到MySQL中的锁,对于MySQL来说,锁是一个很重要的特性

SELECT ... FOR UPDATE: 会对查询的行及相关联的索引记录加X锁,其他事务请求的S锁或X锁都会被阻塞。 当事务提交或回滚后,通过这两个语句添加的锁都会被释放。 注意:只有在自动提交被禁用时,SELECT FOR UPDATE才可以锁定行,若开启自动提交,则匹配的行不会被锁定。

#### 一致性非锁定读

一致性非锁定读(consistent nonlocking read) 是指InnoDB存储引擎通过多版本控制(MVVC)读取当前数据库中行数据的方式。如果读取的行正在执行DELETE或UPDATE操作,这时读取操作不会因此去等待行上锁的释放。相反地,InnoDB会去读取行的一个快照。所以,非锁定读机制大大提高了数据库的并发性。

MySQL的又一神器-锁,MySQL面试必备

一致性非锁定读是InnoDB默认的读取方式,即读取不会占用和等待行上的锁。在事务隔离级别READ COMMITTED和REPEATABLE READ下,InnoDB使用一致性非锁定读。

然而,对于快照数据的定义却不同。在READ COMMITTED事务隔离级别下,一致性非锁定读总是读取被锁定行的最新一份快照数据。而在REPEATABLE READ事务隔离级别下,则读取事务开始时的行数据版本。

下面我们通过一个简单的例子来说明一下这两种方式的区别。

首先创建一张表;

MySQL的又一神器-锁,MySQL面试必备

插入一条数据;

  1. insert into lock_test values(1); 

查看隔离级别;

  1. select @@tx_isolation; 

MySQL的又一神器-锁,MySQL面试必备

下面分为两种事务进行操作。

在REPEATABLE READ事务隔离级别下;

MySQL的又一神器-锁,MySQL面试必备

在REPEATABLE READ事务隔离级别下,读取事务开始时的行数据,所以当会话B修改了数据之后,通过以前的查询,还是可以查询到数据的。

在READ COMMITTED事务隔离级别下;

MySQL的又一神器-锁,MySQL面试必备

在READ COMMITTED事务隔离级别下,读取该行版本最新的一个快照数据,所以,由于B会话修改了数据,并且提交了事务,所以,A读取不到数据了。

5 行锁的算法

InnoDB存储引擎有3种行锁的算法,其分别是:

  •  Record Lock:单个行记录上的锁。
  •  Gap Lock:间隙锁,锁定一个范围,但不包含记录本身。
  •  Next-Key Lock:Gap Lock+Record Lock,锁定一个范围,并且锁定记录本身。

Record Lock:总是会去锁住索引记录,如果InnoDB存储引擎表在建立的时候没有设置任何一个索引,那么这时InnoDB存储引擎会使用隐式的主键来进行锁定。

Next-Key Lock:结合了Gap Lock和Record Lock的一种锁定算法,在Next-Key Lock算法下,InnoDB对于行的查询都是采用这种锁定算法。举个例子10,20,30,那么该索引可能被Next-Key Locking的区间为:

MySQL的又一神器-锁,MySQL面试必备

除了Next-Key Locking,还有Previous-Key Locking技术,这种技术跟Next-Key Lock正好相反,锁定的区间是区间范围和前一个值。同样上述的值,使用Previous-Key Locking技术,那么可锁定的区间为:

MySQL的又一神器-锁,MySQL面试必备

不是所有索引都会加上Next-key Lock的,这里有一种特殊的情况,在查询的列是唯一索引(包含主键索引)的情况下,Next-key Lock会降级为Record Lock。

接下来,我们来通过一个例子解释一下。

  1. CREATE TABLE test (  
  2.     x INT,  
  3.     y INT,  
  4.     PRIMARY KEY(x),    // x是主键索引  
  5.     KEY(y)    // y是普通索引  
  6. );  
  7. INSERT INTO test select 3, 2;  
  8. INSERT INTO test select 5, 3;  
  9. INSERT INTO test select 7, 6;  
  10. INSERT INTO test select 10, 8; 

我们现在会话A中执行如下语句;

  1. SELECT * FROM test WHERE y = 3 FOR UPDATE 

(编辑:常州站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

热点阅读