工作面试老大难 - 锁

news2025/1/19 20:37:46

一、概述

为保证数据的一致性和完整性,需要对 事务间并发操作进行控制 ,因此产生了 锁冲突是影响数据库 并发访问性能 的一个重要因素。所以锁对数据库而言显得尤其重要,也更加复杂。

二、并发问题

  1. MySQL并发事务访问相同记录
    (1)读读情况
    允许这种情况的发生
    (2)写-写情况在这里插入图片描述
    该图描述:当一个事务想对这条记录做改动时,首先会看看内存中有没有与这条记录关联的 锁结构 ,当没有的时候就会在内存中生成一个 锁结构 与之关联等其它事务再次访问该条记录时候,若已经有锁与之关联,那么就需要等待,自身的锁结构为true。
    (3)读写情况
    即一个事务进行读取操作,另一个进行改动操作。这种情况下可能发生 脏读不可重复读幻读 的问题。注意: MySQL在 REPEATABLE READ 隔离级别上就已经解决了 幻读 问题。
  2. 并发问题的解决方案
    (1)方案一:读操作利用多版本并发控制( MVCC ,下章讲解),写操作进行 加锁 。
    (2)方案二:读、写操作都采用 加锁 的方式。
    两个方案对比:
    (1)采用 MVCC 方式的话, 读-写 操作彼此并不冲突性能更高
    (2)采用 加锁 方式的话, 读-写 操作彼此需要 排队执行影响性能

三、锁的分类(不同角度)

在这里插入图片描述

从数据操作的类型划分:读锁、写锁

  1. 读锁 :也称为 共享锁 、英文用 S 表示。针对同一份数据多个事务的读操作可以同时进行而不会
    互相影响
    相互不阻塞的。
  2. 写锁 :也称为 排他锁 、英文用 X 表示。当前写操作没有完成前,它会阻断其他写锁和读锁。
    注意:对于 InnoDB 引擎来说,读锁和写锁可以加在表上也可以加在行上
    对读取的记录加X锁:SELECT … LOCK IN SHARE MODE; SELECT … FOR SHARE;
    对读取的记录加S锁:SELECT … FOR UPDATE;

从锁粒角度划分

表级别

  1. 表级别的 X锁、S锁:普通的读锁、写锁。注意InnoDB 存储引擎提供的表级 S锁 或者 X锁 是相当鸡肋,只会在一些特殊情况下,比方说崩溃恢复过程中用到
  2. 表级别的 意向锁:给更大一级别的空间(数据页或数据表)示意里面是否已经上过锁。注意:也就是说其实IS锁和IX锁是兼容的(IX、IX也兼容)并且它们也都与行级别的X锁、S锁兼容
    在这里插入图片描述
  3. 表级别的 AUTO-INC锁
    系统实现这种自动给 AUTO_INCREMENT 修饰的列递增赋值的原理主要是两个:
    (1)在执行插入语句时就在表级别加一个 AUTO-INC 锁,然后为每条待插入记录的 AUTO_INCREMENT 修饰的列分配递增的值,在该语句执行结束后,再把 AUTO-INC 锁释放掉。这样一来,该语句执行时候,不会受到其它事务的执行语句影响。(不确定要插入数量情况下)
    (2)采用一个轻量级的锁在为插入语句生成 AUTO_INCREMENT 修饰的列的值时获取一下这个轻量级锁,然后生成本次插入语句需要用到的 AUTO_INCREMENT 列的值之后,就把该轻量级锁释放掉不需要等到整个插入语句执行完才释放锁(确定要插入数量情况下)

行级别

  1. 行级别的 记录锁
    普通的读锁(S)锁、写(X)锁。 对一行记录锁定

  2. 行级别的 间隙锁
    引出为了解决幻读问题而生
    概念锁定两条记录之间间隙(左开右开),使其中不能插入数据,也就防止了幻读问题产生
    注意如果对一条记录加了 gap锁 (不论是 共享gap锁 还是 独占gap锁 ),并不会限制其他事务对这条记录加 正经记录锁 或者继续加 gap锁这也说明了间隙锁只为解决防止插入幻影记录而生。
    特例给最后一条记录或者给Supremum加gap锁之后,可以阻止其他事务插入 number 值在 (20, +∞) 这个区间的新记录在这里插入图片描述

  3. 行级别的 临键锁
    概念:一句话,记录锁与间隙锁的合体,左闭右开在这里插入图片描述
    例如这个,在( 3,8 ] 这个区间中在锁还没有释放之前(拥有 gap锁 的该事务提交之前)不能插入记录。也就是,它既能保护该条记录,又能阻止别的事务
    将新记录插入被保护记录前边的 间隙 。

  4. 行级别的 插入意向锁(想要在间隙锁中保护的间隙中插入记录,等待时,会生成一个插入意向锁)
    概念:设计 InnoDB 的大叔规定事务在等待的时候也需要在内存中生成一个 锁结构 ,表明有事务想在某个 间隙 中插入新记录,但是现在在等待。
    注意插入意向锁并不会阻止别的事务继续获取该记录上任何类型的锁

页级别

  1. 页锁
    页锁的开销介于表锁和行锁之间,会出现死锁。锁定粒度介于表锁和行锁之间,并发度一般。
    每个层级的锁数量是有限制的,因为锁会占用内存空间, 锁空间的大小是有限的 。当某个层级的锁数量
    超过了这个层级的阈值时,就会进行 锁升级 。锁升级就是用更大粒度的锁替代多个更小粒度的锁,比如
    InnoDB 中行锁升级为表锁,这样做的好处是占用的锁空间降低了,但同时数据的并发度也下降了。

从锁的态度划分

悲观锁

概念对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据会 阻塞 直到它拿到锁

乐观锁

概念乐观锁认为同一数据的并发操作不会总发生,属于小概率事件不用每次都对数据上锁,但是在更新的时候判断一下在此期间别人有没有去更新这个数据不采用数据库自身的锁机制,而是通过程序来实现。
思路:一条记录,事务A读一次数据version是1然后进行修改判断version是否为1如果读的时候version是1,改的时候还是1,那么这就说明,在两次操作之间没有其它事务对该条记录操作。(以版本号机制为例子)
实现方式:
(1)乐观锁的版本号机制
(2)乐观锁的时间戳机制(原理相同

加锁方式

显示锁

通过特定的语句进行加锁,我们一般称之为显示加锁,例如:
(1)显示加共享锁: select … lock in share mode
(2)显示加排它锁: select … for update

隐式锁

概念一个事务对新插入的记录可以不显式的加锁(生成一个锁结构),但是由于事务id 这个牛逼的东东的存在相当于加了一个 隐式锁 。(必须加一个锁的原因,在一个事务中新插入的记录,并发的事务会对该记录进行读、或者写操作,这就造成了脏读、脏写)

事务id起的作用
(1)对于聚簇索引记录来说,有一个 trx_id 隐藏列,该隐藏列记录着最后改动该记录的 事务id 。那么如果在当前事务中新插入一条聚簇索引记录后,该记录的 trx_id 隐藏列代表的的就是当前事务的事务id ,如果其他事务此时想对该记录添加 S锁 或者 X锁 时,首先会看一下该记录的 trx_id 隐藏列代表的事务是否是当前的活跃事务如果是的话,那么就帮助当前事务创建一个 X锁 (也就是为当前事务创建一个锁结构, is_waiting 属性是 false ),然后自己进入等待状态(也就是为自己也创建一个锁结构, is_waiting 属性是 true )。

(2)对于二级索引记录来说本身并没有 trx_id 隐藏列,在二级索引页面的 Page Header 部分有一个 PAGE_MAX_TRX_ID 属性,该属性代表对该页面做改动的最大的 事务id ,如果 PAGE_MAX_TRX_ID 属性值小于当前最小的活跃 事务id ,那么说明对该页面做修改的事务都已经提交了则此时其他事务直接可以对该记录添加 S锁 或者 X锁, 否则就需要在页面中定位到对应的二级索引记录,然后回表找到它对应的聚簇索引记录,然后再根据该条聚簇索引的trx_id找到这条记录目前所在事务,则会为该事务创建一个 X锁结构,并且自己也创建一个进入等待状态。

其他

全局锁

全局锁就是对 整个数据库实例 加锁。当你需要让整个库处于 只读状态 的时候,可以使用这个命令,之后其他线程的以下语句会被阻塞:数据更新语句(数据的增删改)、数据定义语句(包括建表、修改表结构等)和更新类事务的提交语句。全局锁的典型使用 场景 是:做 全库逻辑备份
全局锁的命令: Flush tables with read lock

死锁

概念:在MySQL中,当多个事务同时请求相同的资源时,可能会发生死锁。死锁是指两个或多个事务互相等待对方释放资源,导致所有事务都无法继续执行的情况。

实际处理
(1)第一种策略,直接进入等待,直到超时。这个超时时间可以通过参数innodb_lock_wait_timeout 来设置。
(2)第二种策略,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务(将持有最少行级排他锁的事务进行回滚),让其他事务得以继续执行。将参数 innodb_deadlock_detect 设置为on ,表示开启这个逻辑。

第二种策略成本分析
(1)如果你能确保这个业务一定不会出现死锁,可以临时把死锁检测关掉。但是这种操作本身带有一定的风险,因为业务设计的时候一般不会把死锁当做一个严重错误,毕竟出现死锁了,就回滚,然后通过业务重试一般就没问题了,这是 业务无损 的。而关掉死锁检测意味着可能会出现大量的超时,这是业务有损 的。
(2)控制并发度。如果并发能够控制住,比如同一行同时最多只有10个线程在更新,那么死锁检测的成本很低。基本思路就是,对于相同行的更新,在进入引擎之前排队,这样在InnoDB内部就不会有大量的死锁检测工作了

避免死锁

  1. 尽量减少事务的持有时间,尽快释放锁。
  2. 尽量减少事务中需要锁定的资源数量,避免同时请求相同的资源。
  3. 尽量按照相同的顺序请求资源,避免交叉锁定。
  4. 使用合适的隔离级别,例如使用READ COMMITTED隔离级别可以减少死锁的发生。
  5. 对于复杂的事务,可以使用分布式事务管理器来协调多个事务的操作,避免死锁的发生。

四、锁内存结构

在这里插入图片描述

五、锁监控

在这里插入图片描述

至此,《MySQL是怎样运行的:从根儿上理解MySQL》,复习结束!

在这里插入图片描述

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

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

相关文章

硬件设计--DAPLINK设计

1 参考网站 1、打造属于你自己的STM32下载器调试器--------DAPLink 2、ARMmebed官方开源代码DAPLink 3、ARMmebed官方开源代码DAPLink github加速网站 4、ARMmebed官方开源硬件旧版 5、ARMmebed官方开源硬件新版 6、自制DAPLink – ARM官方源码以及STM32F103C8T6 7、如何做一个…

软件测试之测试名词解释

1. 白盒测试,英文是white-box testing 是通过程序的源代码进行测试而不使用用户界面。这种类型的测试需要从代码句法发现内部代码在算法,溢出,路径,条件等等中的缺点或者错误,进而加以修正。 2. 黑盒测试,英…

word脚标【格式:第X页(共X页)】

不得不吐槽一下这个论文,真的我好头疼啊。我又菜又不想改。但是还是得爬起来改 (是谁大半夜不能睡觉加班加点改格式啊) 如何插入页码。 格式、要求如下: 操作步骤: ①双击页脚,填好格式,宋体小四和居中都…

除了 Swagger,这个开源 API 管理工具生成文档更高效

提起 Swagger,经常接触接口开发的朋友,一定知道并且都熟练使用了。 Swagger 是一个用于生成、描述和调用 RESTful 接口的 Web 服务。通俗的来讲,Swagger 就是将项目中所有(想要暴露的)接口展现在页面上,并且…

VMware ESXi 8.0U1 发布 - 领先的裸机 Hypervisor

请访问原文链接:https://sysin.org/blog/vmware-esxi-8-u1/,查看最新版。原创作品,转载请保留出处。 作者主页:sysin.org 2023-04-18, VMware vSphere 8.0U1 发布。 详见:VMware vSphere 8 Update 1 新增功能 产品简…

ai智能写作助手-ai自动写作软件

为什么要用ai智能写作工具 在数字化时代,AI(人工智能)技术已经被广泛应用于各种领域,其中之一是写作。AI智能写作工具是利用自然语言处理技术和机器学习算法来生成高质量的文章、博客、新闻稿等。这些工具不仅提供了便捷、高效的…

校园网策列及思路

解决思路一: 适合以下情况也是我现在的学校校园网大概情况: 内网不认证情况下可以互联,除了几个常见端口封闭(目前已知3389),要联网必须认证登录,而且一个号最多两台设备(甚至有时候…

FANUC机器人DCS功能基本介绍

FANUC机器人DCS功能基本介绍 1. 定义 DCS(Dual Check Safety)位置/速度检查功能;利用机器人控制柜中两个独立CPU进行电机速度和位置数据的检查,实时检查位置和速度误差,并通过两个独立的通道关闭电机电源。 DCS功能可以有效地节约占地面积。 DCS功能可以防止机器人工具…

工业通讯应用中主流的常用协议Modbus协议

智联物联技术分享,本期为大家介绍工业通讯常用的主流协议Modbus协议。 Modbus协议的前身叫做Mod协议,常被用于Modicon公司的PLC控制器中,后来Modicon被Schneider收购后随之改名为我们如今所熟悉的modbus协议,现如今广泛应用在物联…

【高级数据结构】红黑树

本文整理红黑树学习过程中的知识点和底层代码实现。 目录 基本概念1、介绍2、应用3、性质 实现红黑树1、原理2、操作1)查找2)插入3)删除 和其他相似结构的对比1、二叉搜索树(BST)2、AVL树1)例子2&#xff0…

Dubbo+Zookeeper 实现服务远程调用

文章目录 一、Dubbo 架构图二、Zookeeper 注册中心三、SpringBoot 整合 Dubbo3.1 添加依赖3.2 配置服务端3.3 配置消费端3.4 启动测试 四、Dubbo-admin 管理中心4.1 部署服务端4.2 部署前端4.3 访问控制台 提示:以下是本篇文章正文内容,Java 系列学习将会…

Visual Assist X安装失败解决办法

最近重装了VS2017,在重装之前卸载了VA助手,但是等到装好VS再去装VA助手时,总是提示以下错误信息: Visual Assist Installer : An error was reported by Visual Studio VSIXInstaller. See the next window for access to its err…

ElasticJob

官网 :: ElasticJob ElasticJob 是面向互联网生态和海量任务的分布式调度解决方案,由两个相互独立的子项目 ElasticJob-Lite 和 ElasticJob-Cloud 组成。 它通过弹性调度、资源管控、以及作业治理的功能,打造一个适用于互联网场景的分布式调度解决方案&…

如何给厂区做导航地图?智能工厂导航地图解决方案公司

如何给厂区做导航地图?在智慧园区中,基于园区的电子地图地图使用的重要性越来越凸显。但目前在园区信息化应用形式中,广泛缺乏专业电子地图的使用,主要原因是:一是地图系统(GIS)实现繁复,与其他展会业务系统…

GateWay微服务网关的搭建

服务网关 没有服务网关 问题:地址太多|安全性|管理问题 访问商品服务 http://ip地址:9001/goods/findAll 访问广告服务 http://ip地址:9002/brand/findAll 访问用户服务 http://ip地址:9003/user/findAll 在有网关的情况下,我们配置网关端口号为…

Vue2之webpack篇(二)Loader

目录 一、loader处理css 1、css文件的创建 2、安装css-loader 3、配置 4、打包 5、最终效果 二、loader处理图片 1、引入图片 2、安装file-loader 3、配置module 4、webpack打包 三、ES6转ES5 1、介绍 2、安装babel-loader 3、webpack.config.js配置 4、webpack打…

C++数据结构:二叉树

二叉树 每个结点最多只有二棵子树,也就是二叉树中没有度大于2的结点。二叉树的子树有左右之分,严格区分左孩子、右孩子,其次序不能颠倒 二叉树五种基本形态 特殊二叉树 斜树 所有节点都只有左子树的二叉树叫做左斜树,所有节点都…

SAP ABAP 创建后台定时任务job

定时任务的事务码 sm36:创建定时任务 sm37:查看定时任务 JDBG:后台任务debug,在对应的sm37中对应的job页面 t-code输入 创建定时任务SM36 1、名称可以随便起一般都是按自己公司业务情况来,比如我这个就是哪一个报表的定时任务,做的是什么操作&#xf…

Python 全栈系列220 Tornado的服务搭建

说明 想法变的真快 本来是没打算用Tornado的,主要是想节约时间。但是现在看来不用还是不行:目前用gevent flask部署的时候,启动多核的worker似乎存在问题。 另外,有很多内部基础的数据服务,其实并不需要flask的各种组…

如何使用镭速保护云存储数据安全

近年来,随着云计算的发展,远程系统上的数据存储变的越来越重要。云存储是一个以数据存储和管理为核心的云计算系统,给我们提供了一种全新的数据信息存储模式。但是,可以从全球任何地方访问和检索相同的数据。所需要的只是一个简单…