MySQL面试篇章—MySQL锁机制

文章目录

  • MySQL的锁机制
    • 表级锁 & 行级锁
    • 排它锁和共享锁
    • InnoDB行级锁
      • 行级锁
      • 间隙锁
      • 意向共享锁和意向排它锁
    • InnoDB表级锁
    • 死锁
    • 锁的优化建议
    • MVCC多版本并发控制
    • MyISAM表级锁
      • 表级锁
      • 并发插入优化
      • 锁调度优化

MySQL的锁机制

表级锁 & 行级锁

表级锁:对整张表加锁,开销小,加锁快,不会出现死锁;但是锁粒度大,发生锁冲突的概率高,并发度低

行级锁:对某行记录加锁,开销大,加锁慢,会出现死锁;但是锁粒度小,发生锁冲突的概率最低,并发度高。

排它锁和共享锁

排它锁(Exclusive),又称为X锁,写锁

共享锁(Shared),又称为S锁,读锁

X锁和S锁之间有以下的关系:SS锁可以兼容,但是XS、SX、XX之间是互斥的,会导致堵塞

  • 一个事务对数据对象O加了S锁,可以对O进行读取操作,但是不能进行更新操作,加锁期间其他事务能对O加S锁,但不能加X锁
  • 一个事务对数据对象O加了X锁,就可以对O进行读取和更新。但是加锁期间其他事务不能对O加任何的锁
# 显式加锁
select ... lock in share mode; # 强制获取共享锁select ... for update; # 获取排它锁

InnoDB行级锁

行级锁

InnoDB存储引擎支持事务处理,表支持行级锁定,并发能力更好

1、InnoDB行锁是通过给索引上的索引项加索来实现的,而不是给表的行记录加锁实现的,这就意味着只有通过索引条件检索数据,InnoDB才使用行级锁,否则InnoDB将使用表锁(因此如果过滤条件没有索引的话,默认加的就是表锁,不是行锁)

2、由于InnoDB的行锁是针对索引字段添加的锁,不是针对行记录加的锁,因此虽然访问的是InnoDB引擎下表的不同行,但是如果使用相同的索引字段作为过滤条件的话,依然会发生锁冲突,只能串行进行,不能并发进行

3、即使SQL使用了索引,但是经过MySQL的优化器后,如果认为全表扫描比使用索引效率更高,此时会放弃使用索引,因此也不会使用行锁,而是使用表锁,因此比如对一些很小的表,MySQL就不会去使用索引

间隙锁

当我们用范围条件而不是相等条件检索数据,并请求共享或排它锁时,InnoDB会给符合条件的已有数据记录的索引项加索;对于键值在条件范围内但并不存在的记录,叫做“间隙(GAP)”,InnoDB也会对这个”间隙“加索,这种锁机制就是所谓的间隙锁。例如:加入user表中只有101条记录,其userId的值分别是1,2,…,100,101,下面的SQL:

select * from user where userId > 100 for update;

这是一个范围条件的检索,InnoDB不仅会对符合条件的userId的值为101的记录加索,也会对userId大于101(虽然记录不存在)的”间隙“加锁,防止其他事务在表的末尾增加数据

InnoDB使用间隙锁的目的,是为了防止幻读,以满足串行化隔离级别的要求,对于上面的例子,要是不使用间隙锁,如果其他事务插入了userId大于100的任何记录,那么本事务如果再次执行上述语句,就会发生幻读

意向共享锁和意向排它锁

意向共享锁(IS锁):事务计划给记录加行共享锁,事务在给一行记录加共享锁前,必须要先获取该表的IS锁。

意向排它锁(IX锁):事务计划给记录加行排它锁,事务在给一行记录加排它锁前,必须要先获取该表的IX锁。

XIXSIS
X互斥互斥互斥互斥
IX互斥兼容互斥兼容
S互斥互斥兼容兼容
IS互斥兼容兼容兼容

1、意向锁是由InnoDB存储引擎获取行锁之前自己获取的

2、意向锁之前都是兼容的,不会产生冲突(即IX和IS)

3、意向锁存在的意义是为了更高效的获取表锁(表格中的X和S指的是表锁,不是行锁!!!)

4、意向锁是表级锁,协调表锁和行锁的共存关系。主要目的是显示事务正在锁定某行或者试图锁定某行

InnoDB表级锁

在绝大部分情况下都应该使用行锁,因为事务和行锁往往是选择InnoDB的理由,但个别情况下也使用表级锁:

1)事务需要更新大部分或者全部数据,表又特别大,如果使用默认的行锁,不仅这个事务执行效率低,而且可能会造成其他食物长时间等待和锁冲突

2)事务涉及多个表,比较复杂,很可能会引起死锁,造成大量事务回滚

例如:

lock table user read; 读锁锁表
lock table user write; 写锁锁表事务执行commit / rollback; 事务提交或者回滚
unlock tables; 本身自带提交事务,释放线程占用的所有表锁

死锁

MyISAM表锁是 deadlock free 的,这时因为MyISAM总是一次获得所需的全部锁,要么全部满足,要么等待,因此不会出现死锁。但是在InnoDB中,除单个SQL组成的事务外,锁是逐步获取的,即锁的粒度比较小,这就决定了在InnoDB中发生死锁是可能的

select * from test_dead_lock where id = 1 for update;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting
transaction

注意:死锁问题一般都是由我们自己的应用造成的,和多线程编程的死锁情况相似,大部分都是由于我们多个线程在获取多个锁资源的时候,获取的顺序不同而导致的死锁问题。因此我们应用在数据库的多个表做更新的时候,不同的代码段,应对这些表按相同的顺序进行更新操作,以防止锁冲突导致死锁问题

锁的优化建议

  • 尽量使用较低的隔离级别
  • 设计合理的索引并尽量使用索引访问数据,使加锁更加准确,减少锁冲突的机会提高并发能力
  • 选择合理的事务大小,小事务发生锁冲突的概率小
  • 不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行,这样可以大大减少死锁的机会
  • 尽量使用相等条件访问数据,这样可以避免间隙锁对并发插入的影响
  • 不要申请超过实际需要的锁级别
  • 除非必须,查询时不要显示加锁

MVCC多版本并发控制

MVCC是多版本并发控制(Multi-Version Concurrency Control,简称MVCC),是MySQL中基于乐观锁理论实现隔离级别的方式,用于实现已提交读和可重复读隔离级别的实现,也经常被称为多版本数据库。MVCC机制会生成一个数据请求时间点的一致性数据快照(Snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取。从用户的角度来看,好像是数据库可以提供同一数据的多个版本(系统版本号和事务版本号)

MVCC多版本并发控制中,读操作可以分为两类:

1、快照读(snapshot read)

  • 读的是记录的可见版本,不用加锁。如select

2、当前读(current read)

  • 读取的是记录的最新版本,并且当前读返回的记录。如insert、delete、update、select … lock in share mode / for update

MVCC:每一行记录实际上有多个版本,每个版本的记录除了数据本身之外,增加了其他字段

DB_TRX_ID:记录当前事务ID

DB_ROLL_PTR:指向undo log日志上数据的指针

**已提交读:**每次执行语句的时候都重新生成一次快照(Read View),每次select查询时

**可重复读:**同一个事务开始的时候生成一个当前事务全局性的快照(Read View),第一次select查询时

快照内容读取原则:

1、版本未提交无法读取生成快照

2、版本已提交,但是在快照创建后提交的,无法读取

3、版本已提交,但是在快照创建前提交的,可以读取

4、当前事务内自己的更新,可以读到

MyISAM表级锁

MyISAM存储引擎不支持事务处理,因此它的并发比较简单,只支持到表锁的粒度,粒度特别大,并发能力一般,但不会引起死锁的问题,它支持表级共享的读锁和互斥的写锁

表级锁

  • 对 MyISAM 表的读操作(共享锁),不会阻塞其他用户对同一表的读请求,但会阻塞对同一表的写请求;

  • 对 MyISAM 表的写操作(排它锁),则会阻塞其他用户对同一表的读和写操作。

  • MyISAM 表的读操作与写操作之间,以及写操作之间是串行的。

  • MyISAM 在执行查询语句(SELECT)前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE、 DELETE、INSERT 等)前,会自动给涉及的表加写锁,这个过程并不需要用户控制,是MySQL Server 端自动完成的。

并发插入优化

  • concurrent_insert优化
show variables like 'concurrent_insert';

普通情况下,MyISAM的读操作和写操作都是串行的,但是其实MyISAM也是支持读和写的并发操作的,上面的concurrent_insert变量就是开关,允许一个线程在读的时候,另外一个线程在尾部进行插入(但是不能并发进行删除delete和更新update)

锁调度优化

  • low_priority_updates优化

在MyISAM存储引擎下,多个线程并发操作时,线程1试图获取读锁,线程2获取写锁,一般MyISAM认为写操作要比读操作重要,因此线程2几乎都会有限获取写锁,写操作完成后,线程1才会获取读锁。

即使线程1的读锁请求先到达,线程2的写锁请求到达后,那么线程2写锁的获取也会排在线程1读锁的前面

因此,MyISAM存储引擎不适合大量的更新操作和查询操作,因为查询操作获取读锁的优先级比较低,会导致客户端查询获取结果的过程很慢。当然MySQL提供了很多参数设置,可以调整读锁的获取优先级。

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

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

相关文章

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级

uniapp实现局域网(内网)中APP自动检测版本,弹窗提醒升级 在开发MES系统的过程中,涉及到了平板端APP的开发,既然是移动端的应用,那么肯定需要APP版本的自动更新功能。 查阅相关资料后,在uniapp的…

【初阶数据结构】复杂度算法题篇

旋转数组 力扣原题 方案一 循环K次将数组所有元素向后移动⼀位(代码不通过) 时间复杂度O(n2) 空间复杂度O(1) void rotate(int* nums, int numsSize, int k) {while (k--) {int end nums[numsSize - 1];for (int i numsSize - 1; i > 0; i--) {nums[i] num…

Redis:十大数据类型

键(key) 常用命令 1. 字符串(String) 1.1 基本命令 set key value 如下:设置kv键值对,存货时长为30秒 get key mset key value [key value ...]mget key [key ...] 同时设置或者获取多个键值对 getrange…

【NPU 系列专栏 2.6 -- - NVIDIA Xavier SoC】

文章目录 NVIDIA Xavier SoCXavier 主要组件Xavier SoC 的型号Xavier SoC 的算力Xavier AGXXavier NXXavier 应用场景自动驾驶机器人物联网(IoT)医疗设备NPU 对比SummaryNVIDIA Xavier SoC 英伟达 Xavier SoC 是英伟达推出的一款高性能系统级芯片,专门为人工智能(AI)和自…

scratch聊天机器人 2024年6月scratch四级 中国电子学会图形化编程 少儿编程等级考试四级真题和答案解析

目录 scratch聊天机器人 一、题目要求 1、准备工作 2、功能实现 二、案例分析 1、角色分析 2、背景分析 3、前期准备 三、解题思路 1、思路分析 四、程序编写 五、考点分析 六、推荐资料 1、入门基础 2、蓝桥杯比赛 3、考级资料 4、视频课程 5、python资料 s…

MongoDB 查询文档

MongoDB 查询文档 MongoDB 是一种流行的 NoSQL 数据库,它使用文档存储数据。在 MongoDB 中,查询文档是一个强大的功能,允许用户从数据库中检索特定数据。本文将详细介绍 MongoDB 查询文档的基础知识、高级用法以及最佳实践。 基础查询 在 MongoDB 中,最基本的查询是使用…

C/C++基础知识

数据类型 目录 数据类型 基本数据类型 变量所占大小 char 构造类型 数组 1.一维数组 2.二维数组 结构体 联合体 指针 内存的申请与释放 C中的new malloc malloc与new的异同 C中的delete free new和delete是如何实现的 malloc和free的实现 被free回收的内存是立即还给操作…

面试题:为什么 一般 weight 选择对称量化,activation 选择非对称量化?

模型的剪枝是为了减少参数量和运算量,而量化是为了压缩数据的占用量。 量化概念 所谓的模型量化就是将浮点存储(运算)转换为整型存储(运算)的一种模型压缩技术。 优势: 可以提升计算效率;减少…

泛微开发修炼之旅--40考勤管理篇:根据班次规则、考勤组规则(含固定值和排班制),在三方系统中获取考勤签到数据,并同步到考勤管理中的解决方案

一、需求描述 我们最近在项目上遇到了一个需求,需要将工厂门禁刷脸数据,通过考勤管理配置的规则,获取到对应的考勤签到数据,依次作为上下班打卡的时间,以此作为员工每天考勤的依据,客户的考勤比较复杂&…

《python程序语言设计》第6章15题财务应用程序:打印税款表。利用程序清单4-7的代码

6.15 打印税款表 def computeTax(status_n, income):tax 0if status_n 0:if income < 8350:tax income * 0.10elif income < 33950:tax 8350 * 0.10 (income - 8350) * 0.15elif income < 82250:tax 8350 * 0.10 (33950 - 8350) * 0.15 (income - 33950) * 0.…

Vue2生命周期+八个钩子函数解析

一.vue生命周期的几个基本概念和常见问题 1.什么是vue的生命周期? 答案&#xff1a;一个vue实例从创建到销毁的过程。 2.vue生命周期有哪几个阶段? 答案&#xff1a;生命周期有四个阶段 分为以下四个阶段&#xff08;有的可能叫法不一样&#xff09; 创建 挂载更新销毁…

《九界ol游戏源码》(游戏源码+客户端+服务端+工具+视频教程)喜欢研究游戏源码的看过来...

《九界》游戏以网络同名热门小说为文化蓝本&#xff0c;构筑了一个地海陆空四维冒险的庞大游戏世界。《九界》以“团队修真”为核心研发理念&#xff0c;引擎采用OGRE引擎&#xff0c;GUI的设计采用CEGUI&#xff0c;游戏设计&#xff0c;地图&#xff0c;音效都是花费了相当的…

哈默纳科HarmonicDrive谐波减速机的使用寿命计算

在机械传动系统中&#xff0c;减速机的应用无处不在&#xff0c;而HarmonicDrive哈默纳科谐波减速机以其独特的优势&#xff0c;如轻量、小型、传动效率高、减速范围广、精度高等特点&#xff0c;成为了众多领域的选择。然而&#xff0c;任何机械设备都有其使用寿命&#xff0c…

Python爬虫-中国汽车市场月销量数据

前言 本文是该专栏的第34篇,后面会持续分享python爬虫干货知识,记得关注。 在本文中,笔者将通过某汽车平台,来采集“中国汽车市场”的月销量数据。 具体实现思路和详细逻辑,笔者将在正文结合完整代码进行详细介绍。废话不多说,下面跟着笔者直接往下看正文详细内容。(附…

Java笔试面试题AI答之线程Thread(1)

答案来自 Kimi AI 目录 1. 进程和线程的区别&#xff1f;2. Java语言创建线程的方式有哪些&#xff1f;3. Java线程有哪几种可用状态&#xff1f;4. Java同步方法和同步代码块的区别&#xff1f;5. 在监视器(Monitor)内部&#xff0c;如何做线程同步的&#xff1f;6. 什么是死…

硅纪元视角 | 语音克隆突破:微软VALL-E 2,Deepfake新纪元!

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

Web前端知识视频教程分享(五) Bootstrap

资料下载地址&#xff1a; https://545c.com/f/45573183-1336822373-45bb4f?p7526 (访问密码: 7526)

Flink内存管理机制

前言 在Flink的后台界面&#xff0c;可以看到整个Flink的内存情况。 如JobManager的内存情况&#xff1a; TaskManager的内存情况 一、Flink内存管理 Flink TaskManager内存组成整体结构图如下&#xff1a; 二、总内存管理 三、JobManager内存管理内存管理 四、TaskManager内…

vue3前端架构---打包配置

最近看到几篇vue3配置项的文章&#xff0c;转载记录一下 Vue3.2 vue/cli-service 打包 chunk-vendors.js 文件过大导致页面加载缓慢解决方案-CSDN博客文章浏览阅读2k次&#xff0c;点赞8次&#xff0c;收藏9次。Vue3.2 vue/cli-service 打包 chunk-vendors.js 文件过大导致页…

Lago - 使用 ClickHouse 扩展事件引擎

本文字数&#xff1a;4540&#xff1b;估计阅读时间&#xff1a;12 分钟 作者&#xff1a;Mathew Pregasen 本文在公众号【ClickHouseInc】首发 本周&#xff0c;我们欢迎来自 Lago 的一篇博客文章&#xff0c;介绍了他们如何使用 ClickHouse 扩展一个事件引擎&#xff0c;并在…