MYSQL篇--锁机制高频面试题

news2024/12/22 18:14:03

Mysql锁机制

1对mysql的锁有了解吗?

首先我们要知道,mysql的锁 其实是为了解决在并发事务时所导致的数据不一致问题的一种处理机制,也就是说 在事务的隔离级别实现中,就需要利用锁来解决幻读问题
然后我们可以聊到锁的分类
按锁的粒度可以分为

  1. 行锁:锁某行数据,锁粒度最⼩,并发度⾼
  2. 表锁:锁整张表,锁粒度最大,并发度低
  3. 间隙锁:锁的是⼀个区间

按锁的性质可以分为

  1. 共享锁:也就是读锁,⼀个事务给某行数据加了读锁,其他事务也可以读,但是不能写
  2. 排它锁:也就是写锁,⼀个事务给某行数据加了写锁,其他事务不能读,也不能写

还可以分为

  1. 乐观锁:并不会真正的去锁某行记录,而是通过⼀个版本号来实现的
  2. 悲观锁:上面所的行锁、 表锁等都是悲观锁

2什么是死锁?怎么解决?

常规回答:死锁它其实是两个或者多个事务在同一个资源上相互占用,同时并请求锁定对方的资源,从而导致恶性循环的现象

解决办法:

  1. 程序再并发存取多个表的时候,尽量让他们以相同的顺序来访问表
  2. 在同一个事务中,尽可能做到一次锁定所需要的所有资源,来避免死锁问题
  3. 对于比较容易产生死锁的部分,可以尝试升级锁的颗粒度,比如使用表级锁,或者分布式事务锁,或者使用乐观锁

3 数据库的乐观锁和悲观锁是什么,如何实现?

首先我们要明白数据库的四大特性,ACID-其中有隔离性,也就是多个事务在并发执行时 他们内部是不能互相干扰的,而悲观锁和乐观锁正是实现隔离性的一种方式

悲观锁:简单的理解就是 它假定会发生并发冲突,在查询完数据的时候就会把事务锁起来,直到提交事务
实现方式:使用数据库中的锁机制–select * for update

乐观锁:它就是说假定不会发生并发冲突,也就是只在提交操作的时候才会检查数据的完整性,在进行修改的时候把事务锁起来
实现方式:版本号机制和cas算法

最后可以总结下:两种锁其实并没有好坏之分,但是却有分别合适的场景,对于乐观锁来说 它其实更适合读多写少的场景,也就是说冲突很少发生的场景,这样的话 就会省去锁的开销,加大系统的吞吐量,相反针对写比较多的场景,乐观锁可能会频繁的冲突,进而导致上层应用不断地retry,这样反倒降低了性能,因此悲观锁更适合写多场景

4 MySQL中InnoDB引擎的行锁是怎么实现的?

首先我们要明白行锁它其实就是记录锁,说白了也就是对表中的记录加锁,简称记录锁,但是注意记录锁-行锁它是锁住索引记录,而不是数据记录,即其实是基于索引来完成的加锁。
你比如说select * from db where a = 1 for update, 这里的for update就是根据条件来完成行锁锁定,并且这里的条件也是有索引建的列,如果a字段不是索引键 将会对整张表加锁
同时记录锁也是排它(X)锁, 所以会阻塞其他事务对其插入、更新、删除。

5 什么是间隙锁-Gap lock?

间隙锁 是 Innodb 在 RR(可重复读) 隔离级别 下为了解决 幻读问题 时引入的锁机制
而间隙锁它其实也算是行锁的一种,另外尤其注意的是间隙锁 它锁住的是一个区间,而不仅仅是这个区间中的每一条数据。
举例来说,假如student表中只有101条记录,其empid的值分别是1,2,…,100,101,

SELECT * FROM student WHERE sid > 100 FOR UPDATE

当我们用条件检索数据,并请求共享或排他锁时,InnoDB不仅会对符合条件的empid值为101的记录加
锁,也会对sid大于101(这些记录并不存在)的“间隙”加锁。
这个时候如果你插入empid等于102的数据的,如果那边事物还没有提交,那你就会处于等待状态,无法插入数据。

6 什么是临键锁(Next-Key Locks)?

Next-key锁是记录锁和间隙锁的组合,它指的是加在某条记录以及这条记录前面间隙上的锁。
也可以理解为一种特殊的间隙锁
通过临建锁可以解决 幻读 的问题。
每个数据行上的非唯一索引列上都会存在一把临键锁,当某个事务持有该数据行的临键锁时,会锁住一段左开右闭区间的数据。
注意:临键锁只与 非唯一索引列 有关,在 唯一索引列(包括主键列)上不存在临键锁。
举个例子
假设有如下表:id主键, age 普通索引
在这里插入图片描述
该表中 age 列潜在的临键锁有:
(-∞, 10],
(10, 24],
(24, 32],
(32, +∞],

在事务 A 中执行如下命令:
– 根据非唯一索引列 UPDATE 某条记录
UPDATE table SET name = Vladimir WHERE age = 24;
– 或根据非唯一索引列 锁住某条记录
SELECT * FROM table WHERE age = 24 FOR UPDATE;

不管执行了上述 SQL 中的哪一句,之后如果在事务 B 中执行以下命令,则该命令会被阻塞:
INSERT INTO table VALUES(100, 26, ‘tianqi’);
很明显,事务 A 在对 age 为 24 的列进行 UPDATE 操作的同时,也获取了 (24, 32] 这个区间内的临键锁。

这里对 记录锁、间隙锁、临键锁 做一个总结:
InnoDB 中的行锁的实现依赖于索引,一旦某个加锁操作没有使用到索引,那么该锁就会退化为表锁 。
记录锁存在于包括主键索引在内的唯一索引中,锁定单条索引记录。
间隙锁存在于非唯一索引中,锁定开区间范围内的一段间隔
临键锁存在于非唯一索引中,该类型的每条记录的索引上都存在这种锁,它是一种特殊的间隙锁,锁定一段左开右闭的索引区间

7 什么是意向锁?

意向锁又分为 意向共享锁(IS) 和 意向排他锁(IX)

意向共享(IS)锁:简单理解就是事务有意向对表中的某些行加共享锁(S锁)
即-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
SELECT column FROM table … LOCK IN SHARE MODE;

意向排他(IX)锁:即事务有意向对表中的某些行加排他锁(X锁)
– 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
SELECT column FROM table … FOR UPDATE;

首先我们要明白四点
意向共享锁(IS)和 意向排他锁(IX)都是表锁。
意向锁是一种 不与行级锁冲突的表级锁,这一点非常重要。
意向锁是 InnoDB 自动加的, 不需用户干预
意向锁是在 InnoDB 下存在的内部锁,对于MyISAM 而言 没有意向锁之说。(即只针对InnoDB

那么问题来了,既然前面已经有了共享锁(S锁)、排它锁(X锁)。
又为什么需要引入意向锁呢?它能解决什么问题呢?
我们可以理解 意向锁 存在的目的就是 为了让 InnoDB 中的行锁和表锁更高效的共存 。
也就是说 如果某个事物要加表锁,如果没有意向锁 那么它就需要去检测表中的每一行是否存在排他锁。很明显这是一个效率很差的做法,
但是有了意向锁之后,情况就不一样了:这个事务只要看表上有没有
意向共享锁,有则说明表中有些行被共享行锁锁住了,因此,事务B申请表的写锁会被阻塞。这样就高效多了

这里我们再来看下 共享(S)锁、排他(X)锁、意向共享锁(IS)、意向排他锁(IX)的兼容性
在这里插入图片描述
可以看出 意向锁之间是互相兼容的.那你存在的意义是啥?
意向锁不会为难意向锁。也不会为难行级排他(X)/共享(X)锁,它的存在是为难 表级 排他(X)/共享(X)锁。
在这里插入图片描述
注意 这里的排他(X)/共享(S)锁指的都是表锁!意向锁不会与行级的共享/排他锁互斥! 行级别的X和S按照上面的兼容性规则即可。
意向锁与意向锁之间永远是兼容的,因为当你不论加行级的X锁或S锁,都会自动获取表级的IX锁或者IS锁。
也就是你有10个事务,对不同的10行加了行级X锁,那么这个时候就存在10个IX锁。
这10IX存在的目的是啥呢,就是假如这个时候有个事务,想对整个表加排它X锁,那它不需要遍历每一行是否存在S或X锁,而是看有没有存在意向锁,只要存在一个意向锁,那这个事务就加不了表级排它X
锁,要等上面10个IX全部释放才行。

8 什么是插入意向锁?

插入意向锁 的特性可以分成两部分:
插入意向锁是一种特殊的间隙锁 —— 间隙锁可以锁定开区间内的部分记录。
插入意向锁之间互不排斥,所以即使多个事务在同一区间插入多条记录,只要记录本身(主键、唯一索引)不冲突,那么事务之间就不会出现冲突等待。
需要强调的是,虽然插入意向锁中含有意向锁三个字,但是它并不属于意向锁而属于间隙锁,因为意向锁 是表锁而 插入意向锁是行锁
总结下:

  1. InnoDB在RR的事务隔离级别下,使用插入意向锁来控制和解决并发插入。
  2. 插入意向锁是一种特殊的间隙锁。
  3. 插入意向锁在锁定区间相同但记录行本身不冲突的情况下互不排斥。

9 MySQL间隙锁,如何解决幻读?

首先我们要知道
在RR的隔离级别下,Innodb使用MVCC和 next-key locks(行锁和间隙锁的组合)解决幻读,
MVCC解决的是普通读(快照读)的幻读
next-key locks解决的是当前读情况下的幻读。
MySQL间隙锁 + 记录锁 ,组合起来,解决的是当前读情况下的幻读

至于MVCC如何解决幻读的 请看 我之前的事务篇
而在这里 我们简单说下什么是当前读和快照读

快照读(历史数据)-mvcc
快照读对应的sql 语法:简单的select操作(不包括 select … lock in share mode, select … for update)

当前读(最新数据)对应的sql 语法:
select * from table where ? lock in share mode;
select * from table where ? for update;
insert into table values (…);
update table set ? where ?;
delete from table where ?;
特殊的读操作,插入/更新/删除操作,属于当前读,需要加锁。
那么解决原理其实就是 保证数据是一致的(也就是一个事务,其内部读取对应某一个数据的时候,数据都是一样的),同时读取的数据是最新的数据。
innodb提供了next-key lock,也就是结合gap锁与行锁,达到最终目的

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1376042.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Windows安装和使用kafka

一、安装kafka 由于kafka依赖jdk和zookeeper,安装kafka之前需要先安装jdk和zookeeper,也可以使用kafka自带的zookeeper。安装jdk可以参考:Windows和Linux安装jdk,此处使用kafka自带的zookeeper,不单独安装。 下面在Wi…

Python列表(list)

目录 列表列表的创建与删除访问列表元素index() 方法 列表的遍历添加,修改和删除列表元素添加修改删除 对列表统计和计算count() 方法如需确定列表中有**多少元素**,请使用 len() 方法:检查项目是否存在**复制列表****合并两个列表****list()…

Win10安装配置Redis,修改密码

一、下载Redis tporadowski 提供了 支持 Windows平台的 Redis 安装包,目前仍在维护,目前最新版本是 5.0.14,更新速度跟Redis官网也相差好几个大版本。 下载地址:https://github.com/tporadowski/redis/releases 二、Redis 安装 …

极客时间-如何降低用户鉴权的流量压力

背景 内容是极客时间-徐长龙老师的高并发系统实战课的个人学习笔记,欢迎大家学习!https://time.geekbang.org/column/article/596644 使用Session方式实现用户的用户鉴权 优点 信息都在服务端储存,对客户端不暴露任何用户敏感的数据信息 缺…

SQL-修改表操作

目录 DDL-表操作-修改 添加字段 (方括号内容可选) 修改字段 修改指定字段的数据类型 修改字段名和字段类型 删除字段 修改表名 删除表 删除指定表,并重新创建该表 总结 🎉欢迎您来到我的MySQL基础复习专栏 ☆* o(≧▽≦…

Window平台安装MongoDB

在部署前需要在官网先确定系统对应的Mongo DB版本。 本机电脑为Window10,所以这里以MongoDB 6.0版本。 1 在官网下载安装包 2 安装MongoDB MongoDB Compass 是一个图形界面管理工具,如果勾选了安装会花费长一点时间,可以取消掉勾选&#xff…

[UI5] ODATA V4中的CRUD

文章目录 前言一、Read二、Create三、Update四、Delete 前言 ODATA V4在CRUD方面与V2截然不同。 这篇文章简单介绍V4中是如何进行CRUD操作 一、Read Model不再有read方法, 一般是把Path绑定到View中进行读取, 如果需要额外的读取数据,可使用…

树状结构查询 - 华为OD统一考试

OD统一考试 分值: 200分 题解: Java / Python / C 题目描述 通常使用多行的节点、父节点表示一棵树,比如: 西安 陕西 陕西 中国 江西 中国 中国 亚洲 泰国 亚洲 输入一个节点之后,请打印出来树中他的所有下层节点。 …

Python: Spire.PDF-for-Python

# encoding: utf-8 # 版权所有 2024 ©涂聚文有限公司 # 许可信息查看: # 描述: # Author : geovindu,Geovin Du 涂聚文. # IDE : PyCharm 2023.1 python 3.11 # Datetime : 2024/1/11 10:32 # User : geovindu # Product : PyChar…

TypeScript类型挑战:实现内置的Omit实用类型

掌握 TypeScript Omit 泛型,一起完成 Type 挑战,巩固 TypeScript 知识。 为了帮助读者更好地巩固 TypeScript 的知识,我从 Github 上的 type-challenges 库中选择了几十个挑战,与您一起完成类型挑战。 挑战 实现内置的 Omit&…

分布式系统架构设计之分布式消息队列的水平扩展性、安全可用性以及监控与调优

一、分布式消息队列的水平扩展 随着业务的快速发展和数据的不断增长,单一的消息队列服务器往往难以满足高并发、高可用和高吞吐量的需求,因此,如何实现消息队列的水平扩展成为了一个重要的问题。这部分我将从分区、副本、负载均衡等关键概念…

影响eCPM的因素有哪些?如何提升eCPM?

eCPM(千次展示有效收益)直接关系广告变现收益的高低,是开发者们最关心的数据之一。要想优化提升eCPM,首先要了解哪些主要因素影响eCPM,再针对性优化广告库存,提高变现收益。 https://www.shenshiads.com …

线性回归实例

1、线性回归(linear Regression)和逻辑回归(logistic Regression)的区别 线性回归主要是用来拟合数据,逻辑回归主要是用来区分数据,找到决策边界。 线性回归的代价函数常用平方误差函数,逻辑回…

java每日一题——打印100以内个位和十位相同,尾数为1,3,5,7的数字

前言: 打好基础,daydayup! 题目:打印100以内个位和十位相同,尾数为1,3,5,7的数字 思路:1,个位通过对10求余数可求出1,3,5,7; 2,十位可通过先除10…

【Unity】【Pico】【VR开发】为何PICO打包后真机运行闪退

【背景】 设置步骤,项目配置都没问题,Build也成功,Unity版本是符合要求的2022LTS版本,但是一在真机上运行就闪退。 【分析】 由于并没有开版权验证,而且闪退后也并没有弹框说版权问题,所以还是怀疑环境有…

软件测试|Python成员运算符:使用方法与元素检查

简介 Python是一种功能强大的编程语言,提供了许多方便的工具来处理数据和集合。其中之一就是成员运算符,它允许我们在集合中检查特定元素的存在。在本文中,我们将深入探讨Python中的成员运算符,以及如何使用它来进行元素检查。 …

pyside6 捕捉主窗口关闭后,进行释放相关的资源

import sys from PySide6 import QtGui from PySide6.QtWidgets import QWidget,QApplication,QMessageBoxclass Message(QWidget):def __init__(self):# 如果希望窗口内嵌于其他部件,可添加parent参数super(Message, self).__init__()# 调用初始化方法self.initUI(…

使用Sqoop将数据导入Hadoop的详细教程

在大数据处理中,Sqoop是一个强大的工具,它可以将关系型数据库中的数据导入到Hadoop生态系统中,以便进行进一步的分析和处理。本文将提供一个详细的教程,以帮助大家了解如何使用Sqoop将数据导入Hadoop。 准备工作 在开始之前&…

【uniapp】新课uniapp零基础入门到项目打包(微信小程序/H5/vue/安卓apk)全掌握

一、uniapp和HBuilderX介绍 uni-app官方网站:https://uniapp.dcloud.net.cn/ 为什么要学习uniapp? 1、一套代码可以打包到不同的应用平台;一套代码编到十几个平台,这不是梦想。眼见为实,扫描以下二维码,…

uniapp微信小程序投票系统实战 (SpringBoot2+vue3.2+element plus ) -用户投票实现

锋哥原创的uniapp微信小程序投票系统实战: uniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )_哔哩哔哩_bilibiliuniapp微信小程序投票系统实战课程 (SpringBoot2vue3.2element plus ) ( 火爆连载更新中... )共计21条视频…