MYSQL中的锁(面试难点重点)

news2024/11/25 6:28:07

首先说一下 这个加锁是个啥子过程呢

我们拿一条记录举例,这个记录就放在这,没人操作它,他就没生成锁结构, 直到有个事务操作它了,然后给它才生成了个锁结构,锁结构两个参数 trx(生成该锁的事务) is_waiting(正在等待就是:true 没在等待就是 false) (锁里面很多参数 这里这是为了方便理解例举了两个),然后下一个事务试图操作这条记录,就会发现本记录已经加上锁了,就要再生成一个锁(本次锁的 等待状态就是:true)

举个例子

有个记录 我们称为 record

然后事务A 对record进行操作 事务开始 record加了一个锁 参数  trx:A  is_waiting:false

然后来了个byd事务B 又想对record进行操作 事务开始 发现 哎?这有个锁了 然后它也生成一个锁

锁参数 trx:B  is_waiting:true   is_waiting:true就代表它正在等待 事务B就停在这里了 直到变成false才能继续执行

然后事务A提交 释放锁 然后事务B获得锁 参数变成trx:B  is_waiting:false 

表级锁

S锁

共享锁(英语原文是share什么玩意 反正S是share 查了一下是Share Locks)  共享锁就是咋的呢 一个事务A对此表加了个S锁 然后又来个事务B试图加了个S锁 这次不会像正常流程一样阻塞 而是会加锁成功 此条记录同时有两个锁(都是is_waiting:false的)

X锁

独占锁(Exclusive Locks) 与其他锁冲突(包括S锁) 

这里就得具体描述了

事务A加了个 X锁 事务B加了个S锁 会阻塞

事务A加了个 S锁  事务B加了个X锁 会阻塞 懂了吧 就是不管X锁先加后加 都会阻塞

事务A加了个 X锁  事务B加了个X锁 阻塞

事务A加了个S锁 事务B加了个S锁 不阻塞 

IS锁:意向共享锁 

IX锁:意向独占锁

这里是啥意思呢 就是说我们的表级锁和行级锁之间也是冲突的 就比如我们行级加了一个X锁

这时我们想在表上加一个X锁 会阻塞 但是我们怎么去看这个表里面有没有行级X锁吗 遍历每条记录吗 那老MYSQL一整几百万条记录 遍历累死

所以提出了 意向锁 IS锁就是说明当前表内有S锁 IX锁就是说明当前表内有X锁

那么这个阻塞的问题呢

IX锁和IX锁冲不冲突? 不冲突 我不同记录加了X锁 这个表也被加入了多次IX锁

那IX和IS锁呢? 也不冲突 不同记录加了X锁 S锁 表上加了IX IS 可以

那X和IX呢? (这里X指表级的)  冲突 IX就说明当前表内有X锁了 而X表级锁和行级锁冲突 (可以把表级锁当做 所有记录都加了行锁呢)

同理 S和IX X和IS....

AUTO-INC锁

眼熟不?像不像某个字段(AUTO_INCREMENT 自增列) 

我们在插入记录的时候 自增列是不需要我们自己指定值的 那么如果多个事务同时插入的时候

就会乱套 所以MYSQL提供了两种解决方法

1.AUTO-INC锁:行插入语句时就在表级别加一个 AUTO-INC 锁,然后为每条待插入记录的 AUTO_INCREMENT 修饰的列分配递增的值,在该语句执行结束后,再把 AUTO-INC 锁释放掉。这样一个事务在持有 AUTO-INC 锁的过程中,其他事务的插入语句都要被阻塞,可以保证一个语句中分配的递增值是连续的。

2.轻量级锁 如果因为一列就阻塞所有插入操作未免有点太耽误时间了 所以就提出了个这么个玩意

在为插入语句生成 AUTO_INCREMENT 修饰的列的值时获取一下这个轻量级锁,然后生成本次插入语句需要用到的 AUTO_INCREMENT 列的值之后,就把该轻量级锁释放掉,并不需要等到整个插入语句执行完才释放锁。

如果我们的插入语句在执行前就可以确定具体要插入多少条记录,比方说我们上边举的关于表 t 的例子中,在语句执行前就可以确定要插入2条记录,那么一般采用轻量级锁的方式对 AUTO_INCREMENT 修饰的列进行赋值。这种方式可以避免锁定表,可以提升插入性能。

对吧对吧 提前知道插入多少记录了 就可以提前准备了

可以通过innodb_autoinc_lock_mode的系统变量来控制到底使用上述两种方式中的哪种来为AUTO_INCREMENT修饰的列进行赋值,当innodb_autoinc_lock_mode值为0时,一律采用AUTO-INC锁;当innodb_autoinc_lock_mode值为2时,一律采用轻量级锁;当innodb_autoinc_lock_mode值为1时,两种方式混着来(也就是在插入记录数量确定时采用轻量级锁,不确定时使用AUTO-INC锁)。不过当innodb_autoinc_lock_mode值为2时,可能会造成不同事务中的插入语句为AUTO_INCREMENT修饰的列生成的值是交叉的,在有主从复制的场景是不安全的.(性能的代价)

顺便说下:表级的X锁 S锁基本用不上 锁住全表实在太重了 耽误事 对应的IX IS锁也不常用

行级锁

重点来了啊重点来了

记录锁(Record Locks)

记录锁分x锁和s锁不多赘述

间隙锁(Gap Locks)

锁如其名 锁住间隙的

假如说有 1  2  3  4这几条记录在 记录3上加间隙锁就是  锁住了2和3之间的间隙 让其他事务无法在这个间隙上面加记录  假如说有一条记录来了 想在2和3之间插入 看一眼它后面的记录 我超!!!!锁!!!!

额 然后就阻塞了

这个 gap锁 的提出仅仅是为了防止插入幻影记录而提出的,虽然有 共享gap锁 和 独占gap锁 这样的说法,但是它们起到的作用都是相同的。而且如果你对一条记录加了 gap锁 (不论是 共享gap锁 还是 独占gap锁 ),并不会限制其他事务对这条记录加 正经记录锁 或者继续加 gap锁 ,再强调一遍, gap锁 的作用仅仅是为了防止插入幻影记录的而已。

啊 你会不会想 那我要是想在最后一条记录前那个卵间隙加记录 那么我缺失的这个锁这一块谁来给我补呢?

每个数据页中有 两个伪记录

Infimum 记录,表示该页面中最小的记录。Supremum 记录,表示该页面中最大的记录。

假如说我在那个(4,正无穷)的这个间隙上面加锁 就直接在这个Supremum 记录就可以了

Next-Key Locks 

我又想锁住记录 又想锁住记录前面的间隙 就使用Next-Key Locks吧!

Next-key Locks本质上等于俩锁  记录锁+间隙锁

Insert Intention Locks

插入意向锁 当一条记录想插入这个间隙的时候 发现这个位置被间隙锁锁住了 于是它在这个时候开始等待 等待的过程生成一个插入意向锁 表示有记录想在这个间隙里面插入记录 但是还在等待

插入意向锁是一种特殊的间隙锁

有个事务A对这个间隙加锁了 然后来了一个事务B 事务C想在这个间隙里面加记录 B C来一看 好嘛

这有个间隙锁 然后他俩生成了插入意向锁 is_wait是false  然后A的间隙锁释放后,他俩就可以获得到插入意向锁(实质上只是is_waiting调整成了true) B和C之间也不会阻塞 可以同时获取到锁 所以有啥用呢

只有当被间隙锁阻塞的时候才会生成插入意向锁

隐式锁

我们前边说一个事务在执行 INSERT 操作时,如果即将插入的 间隙 已经被其他事务加了 gap锁 ,那么本次INSERT 操作会阻塞,并且当前事务会在该间隙上加一个 插入意向锁 ,否则一般情况下 INSERT 操作是不加锁的。那如果一个事务首先插入了一条记录(此时并没有与该记录关联的锁结构)

如果此时对它进行读操作(可以看下面的部分)  SELECT ... LOCK IN SHARE MODE 语句读取这条事务,也就是在要获取这条记录的 S锁 ,或者使用 SELECT ... FOR UPDATE 语句读取这条事务或者直接修改这条记录,也就是要获取这条记录的 X锁,阁下如果不生成任何锁应对的话 就可能产生脏读

立即修改这条记录,也就是要获取这条记录的 X锁 ,该咋办?如果允许这种情况的发生,那么可能产生 脏写 问题。

我们分两种情况讨论解决方案

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

先发现锁冲突 然后再加锁 所以是隐式锁

对于二级索引记录来说,本身并没有 trx_id 隐藏列,但是在二级索引页面的 Page Header 部分有一个 PAGE_MAX_TRX_ID 属性,该属性代表对该页面做改动的最大的 事务id ,如果PAGE_MAX_TRX_ID 属性值小于当前最小的活跃 事务id ,那么说明对该页面做修改的事务都已经提交了,(如果小于说明修改还没开始 如果大于等于说明正在修改了)否则就需要在页面中定位到对应的二级索引记录,然后回表找到它对应的聚簇索引记录,然后再重复 情景一 的做法。

 读时的锁操作

我们前边说在采用 加锁 方式解决 脏读 、 不可重复读 、 幻读 这些问题时,读取一条记录时需要获取一下该记录的 S锁 ,其实这是不严谨的,有时候想在读取记录时就获取记录的 X锁 ,来禁止别的事务读写该记录

对读取的记录加 S锁 : SELECT ... LOCK IN SHARE MODE;

对读取的记录加 X锁 : SELECT ... FOR UPDATE;

这里的X锁仍与S锁冲突(会阻塞)

当前读时(update、insert、delete,这些语句执行前都会查询最新版本的数据,然后再做进一步的操作)  会在读的范围上加一个间隙锁

写时的锁操作

DELETE :对一条记录做 DELETE 操作的过程其实是先在 B+ 树中定位到这条记录的位置,然后获取一下这条记录的 X锁 ,然后再执行 delete mark 操作。我们也可以把这个定位待删除记录在 B+ 树中位置的过程看成是一个获取 X锁 的 锁定读 

UPDATE:

如果未修改该记录的键值并且被更新的列占用的存储空间在修改前后未发生变化 则先在 B+ 树中定位到这条记录的位置,然后再获取一下记录的 X锁 ,最后在原记录的位置进行修改操作。其实我们也可以把这个定位待修改记录在 B+ 树中位置的过程看成是一个获取 X锁 的 锁定读 

如果未修改该记录的键值并且至少有一个被更新的列占用的存储空间在修改前后发生变化,则先在B+ 树中定位到这条记录的位置,然后获取一下记录的 X锁 ,将该记录彻底删除掉(就是把记录彻底移入垃圾链表),最后再插入一条新记录。这个定位待修改记录在 B+ 树中位置的过程看成是一个获取 X锁 的 锁定读 ,新插入的记录由 INSERT 操作提供的 隐式锁 进行保护。

如果修改了该记录的键值,则相当于在原记录上做 DELETE 操作之后再来一次 INSERT 操作,加锁操作就需要按照 DELETE 和 INSERT 的规则进行了。

注意后两种的区别 记录移入垃圾链表和DELETE操作是不同的

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

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

相关文章

Linux/Unix-gcc编译回顾

1、gcc编译为可执行程序四步骤:预处理->编译->汇编->链接 注意:-o 用于修改生产的文件名 2、gcc常用参数 指定头文件:-I 语法: gcc -I 头文件所在文件夹路径 源文件 -o 生成文件名 如果头文件和源文件中同一个文件夹…

事务的实现原理

事务的实现 简介特性(ACID)状态与分类 实现机制日志机制redo logundo log 锁机制 如何使用 简介 有许多小伙伴初学事务还不太清楚是干什么的,那么我们在简介中一次性将事务给搞懂 首先我们先来简单的说一下事务是什么,以便更好的去…

企业数据治理实战总结--数仓面试必备

文章整理自涤生大数据老师宇哥,宇哥是历任中国电信,平安银行,微众银行,众安保险等多家公司擅长大数据求职面试,数仓开发管理,数据治理,数据质量等工作,主导过相关平台的建设 1 数据…

mybatis和dbeaver安装部署连接测试

ORM对象关系映射,把对象和数据库中的数据进行映射。mybatis是orm框架,mybatis-plus是mybatis的增强工具,简化开发。 1.准备mysql数据库 首先安装mysql https://dev.mysql.com/downloads/file/?id518835 设置密码:0000 然后下db…

大数据学习01-Zookeeper分布式集群部署

二、下载 zookeeper官网,本文使用的是zookeeper3.4.8版本 三、安装部署 将下载好的安装包上传至linux服务器上 解压安装包 tar -zxvf zookeeper-3.4.8.tar.gz -C /home/localzookeeper目录重命名 mv zookeeper-3.4.8 zookeeper配置环境 vim /etc/profile添加…

自定义实现list及其功能

#pragma once #include <iostream> #include <assert.h> using namespace std;namespace test {//******************************设置结点******************************template<class T>struct list_node{T _data;list_node<T>* _next;list_node&l…

SQL27 查看不同年龄段的用户明细

selectdevice_id,gender,casewhen age>25 then 25岁及以上when age>20 then 20-24岁when age<20 then 20岁以下else 其他end as age_cut from user_profile

Python property 定义与应用

目录 一、前言二、定义 一、前言 在 Python 类这一节中&#xff0c;会涉及到属性的私有化&#xff0c;私有化的好处在于我们无法轻易地更改类体中属性值&#xff0c;而对于类体中的私有化属性其实也并非真正的私有化&#xff0c;而是一种伪私有化&#xff0c;我们可通过 dir()…

71、redis主从复制的核心原理

redis主从复制的核心原来 通过执行slaveof命令或设置slaveof选项&#xff0c;让一个服务器去复制另一个服务器的数据。主数据库可以进行读写操作&#xff0c;当写操作导致数据变化时会自动将数据同步给从数据库。而从数据库一般是只读的&#xff0c;并接受主数据库同步过来的数…

Android JetPack Compose之主题的理解与使用

目录 概述1.什么是MaterialTheme2.MaterialTheme与CompositionLocal的联系2.1 MaterialTheme的工作原理2.2 CompositionLocal2.3 CompositionLocal的两种创建方式2.3.1 compositionLocalOf2.3.2 staiticCompositionLocalOf 2.4 CompositionLocal总结 概述 根据百度百科知识&am…

Springboot + Vue 上传Word文档并保留内部格式

因为业务需求&#xff0c;上传Word文件需要编辑&#xff0c;但如何使用Blob方式&#xff0c;在数据库里存文件&#xff0c;就会造成格式消失。所以修改思路&#xff1a;上传文件到服务器本地&#xff0c;保证数据存储的完整性。 前端 <el-upload class"upload-demo&quo…

复习PHP基础教程

PHP 安装 PHP 简介PHP 语法 我需要什么&#xff1f; 如需开始使用 PHP&#xff0c;您可以&#xff1a; 使用支持 PHP 和 MySQL 的 web 主机在您的 PC 上安装 web 服务器&#xff0c;然后安装 PHP 和 MySQL。 使用支持 PHP 的 Web 主机 如果您的服务器支持 PHP&#xff0c…

基数排序|RadixSort|C++实现

前言 那么这里博主先安利一些干货满满的专栏了&#xff01; 首先是博主的高质量博客的汇总&#xff0c;这个专栏里面的博客&#xff0c;都是博主最最用心写的一部分&#xff0c;干货满满&#xff0c;希望对大家有帮助。 高质量干货博客汇总https://blog.csdn.net/yu_cblog/c…

电商 api 接口文档

电商 api 接口文档 1、开篇 欢迎使用ShowDoc&#xff01; API格式&#xff1a; 备注&#xff1a;电商API必须返回如下3个字段&#xff1a; 参数名必选类型说明status是int状态message是string信息提示result否mix结果 2、用户相关 2.1、登录/退出 简要描述&#xff1a; …

【复盘】记录一次类型不一致导致的Kafka消费异常问题

背景 业务主要是通过A系统向B系统写入Kafka&#xff0c;然后B系统消费Kafka 将结果写到Kafka中&#xff0c;A进行消费最终结果。 在整个流程中&#xff0c;A写入Kafka会写入一张 record1表记录&#xff0c;然后在A消费最终结果的时候也记录一张record2表。主要改动的话 只是B系…

从Web2到Web3:区块链技术的未来前景

随着互联网的发展&#xff0c;Web1.0、Web2.0 和 Web3.0 成为了人们口中津津乐道的话题。那么&#xff0c;这三种网络时代究竟有什么区别呢&#xff1f; Web1.0 是一个只读的时代&#xff0c;那个时候&#xff0c;用户只能浏览网页&#xff0c;无法进行互动和创作。Web2.0 则是…

什么是社会智商?24种人格力量之社会智商的力量

什么是社会智商&#xff1f; 社会智商指的是将人的智力具体化&#xff0c;自己对他人的了解以及自我剖析能力的高低。一般而言&#xff0c;社会智商越高&#xff0c;对他人的观测能力越高&#xff0c;自我剖析就越透彻。社会智商来源于via 24种人格力量&#xff0c;是人格的优…

FPGA实现UART协议的接收与发送

一、接收模块uart_rx.v UART协议&#xff0c;空闲时&#xff0c;TX和RX数据线都是通过上拉电阻拉高的状态&#xff0c;这样才能在起始位到来时检测到一个下降的边沿。 UART数据格式 uart_rx.v模块输入输出示意图 RX_start。首先&#xff0c;找到起始位的开始时刻RX_start&…

在程序员从业生涯中,哪本书让你醍醐灌顶?

推荐《程序员的README》 [美] 克里斯里科米尼&#xff08;Chris Riccomini&#xff09; 著&#xff0c;付裕 译 每名新入行的工程师在开始工作之前要阅读的书&#xff01;10年大型公司初级工程师指导经验的行业大咖教你如何开启职业生涯、扩展工作技能、应对糟糕管理&#xff0…

信音电子在创业板IPO:募资约9亿元,预计上半年收入约4.3亿元

7月17日&#xff0c;信音电子&#xff08;中国&#xff09;股份有限公司&#xff08;下称“信音电子”&#xff0c;SZ:301329&#xff09;在深圳证券交易所创业板上市。本次上市&#xff0c;信音电子的发行价为21.00元/股&#xff0c;发行数量为为4300万股&#xff0c;募资总额…