MySQL锁机制与优化实践

数据库乐观和悲观锁

乐观锁

比如在数据库中设置一个版本字段,每操作一次,都会将这行对应的版本号+1,这样下次更新都会拿到最新的版本号更新,如果一个事务拿到了版本号但是更新前其他人已经将版本号升级了,那么当前事务就会更新不到这条数据。也就达到了隔离的效果

悲观锁

直接加锁,加了锁以后其他进来访问就访问不了

锁分类

读锁

select * from 表名 where id=1 lock in share mode

读锁不互斥,同一个数据多个读操作不会互斥,可以同时进行

写锁

select * from 表名 where id=1 for update

写锁互斥,操作同一个数据,其中一个给这个数据加上了写锁,那么其他的操作就只能等待,等这个操作的写锁取消了才能再进行操作。

意向锁

主要是为了针对表锁,当想要给表加锁可能还要遍历当前表每一行数据看看有没有加行锁,但是意向锁的作用就是如果当前表加了行锁就会给表加一个标识代表当前表有行锁,这时候如果要加表锁就会发现表中有行锁。

间隙锁

上图中表可以看到主键id是断断续续的,那么现在有一个场景

当前隔离级别是MySQL默认隔离界别(可重复读)。

会给主键中缺少的数据加一个锁,比如10-15中间没数据,15-20中间没数据。

所以会加一个 (10,15)、(15,20)加锁。比如id > 1 and id <= 16 for update会加一个行锁在 1-16之间,但是又因为有间隙锁 15-20.所以在 1-20中间都会加锁,这时候其他事务想要插入或者修改1-20之间的数据都是要等待上个锁释放掉

临建锁

案例:有一个事务A 读取 id > 1 and id <= 16 for update;

事务A没提交事务并且加了行锁,这时事务B进来写了一个插入语句,并且id = 16

因为有间隙锁那么就会给 10-15、15-20这中间加锁,但是又因为上边加了行锁在 1-16之间。但是临建锁会因为16在 间隙锁15-20之间取大的也就是20进行加锁。这时即使查询是 1<id<=16但是因为间隙锁的缘故也会导致 1-20之间的数据都加了锁

示例2

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
	BEGIN;
	UPDATE account 
SET `name` = 12 WHERE id < 13 and id > 1;

上边这个sql这是没有提交,因为在可重复度级别下会自动给update语句加一个行锁,但是由于间隙锁和临建锁的缘故,再去插入 id为1-13之间空缺的数据肯定不能成功的,必须等上边update语句提交或者回滚。

表锁

锁住整张表,其他操作都不能进来操作这张表

页数

锁住一页,但是这里的一页并不是我们分页查询的一页。

而是在索引树中一块存储的页,如下图

上边这才是一页,类似于Java中的分段锁一样

行锁

锁住一行数据,比如给 id = 1 的数据加了写锁,这是其他操作来修改id=2的数据也是可以成功的。也就是给当前行加锁并不影响其他人操作其他行数据。

但是这个锁必须要使用索引,如果加锁的字段不是索引,就会导致这个行锁升级为表锁。是不是主键索引都可以,但是只能走索引,不然就是表锁,如果走了不是主键索引而是普通索引,那么锁就是锁的就是普通索引.

比如有普通索引 ind_name(name);这时修改 update table set age = 10 where name = 'lilei';

而上边修改事务没提交,其他事务来新增 数据 其中name就是lilei,按照道理来说可以成功,但是这个 新增操作却 需要锁等待,因为当前锁是锁的name=lilei 只要是操作name = lilei的数据的人都会锁等待

锁问题分析

‐‐ 查看事务
2 select * from INFORMATION_SCHEMA.INNODB_TRX;
3 ‐‐ 查看锁,8.0之后需要换成这张表performance_schema.data_locks
4 select * from INFORMATION_SCHEMA.INNODB_LOCKS;
5 ‐‐ 查看锁等待,8.0之后需要换成这张表performance_schema.data_lock_waits
6 select * from INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
7
8 ‐‐ 释放锁,trx_mysql_thread_id可以从INNODB_TRX表里查看到
9 kill trx_mysql_thread_id
10
11 ‐‐ 查看锁等待详细信息
12 show engine innodb status;

上边操作可以查看当前锁的竞争情况,也可以查询锁的数量和状态和执行的sql语句,这样如果需要优化也可以看这个进行优化。

比如死锁,简单的死锁MySQL会自己进行处理,kill掉死锁的事务。复杂的MySQL处理不了我们可以通过上边锁情况进行自己手动处理。

锁的优化

  1. 事务尽量小一点 不然锁会一直等待
  2. 尽可能让所有数据检索都都走索引,这样不会表锁
  3. 降低事务隔离级别

MVCC多版本并发控制机制

可重复读

mvcc的undo回滚日志

表中的每一条数据当被事务进行了修改,那么都会有一个这条数据的undo回滚日志。其中包含了表中的字段还有额外的两个字段 trx_id 操作的事务id。roll_polnter 是记录了当前操作回滚的undolog日志地址,比如当前事务操作了 insert 插入一个id=1的数据,那么undolog就会对应一个delete id = 1的操作,如果需要回滚就会执行这个反操作delete。

mvcc的可见性算法

有一个read-view。开启事务并不会立即记录read-view ,而是开始了事务执行任意查询语句会将当前MySQL全部的事务都记录下来。比如事务A开启之后,MySQL此时存在 事务id分别为: 100,200,300,400,500,600,还有一个700已经提交了。 这时候就会记录成一个数组 (100,200,300,400,500,600 ),700 .

结构为: (未提交的事务id),当前存在的事务最大id(不管提每提交)

这样构建的read-view为 (100,200,300,400,500,600),700。具体如何用看下一个怎么完成的隔离性。

版本链比对规则:

1. 如果 row 的 trx_id 落在绿色部分( trx_id<min_id ),表示这个版本是已提交的事务生成的,这个数据是可见的;

2. 如果 row 的 trx_id 落在红色部分( trx_id>max_id ),表示这个版本是由将来启动的事务生成的,是不可见的(若 row 的

trx_id 就是当前自己的事务是可见的);

3. 如果 row 的 trx_id 落在黄色部分(min_id <=trx_id<= max_id),那就包括两种情况

a. 若 row 的 trx_id 在视图数组中,表示这个版本是由还没提交的事务生成的,不可见(若 row 的 trx_id 就是当前自己的

事务是可见的);

b. 若 row 的 trx_id 不在视图数组中,表示这个版本是已经提交了的事务生成的,可见

那么事务中是怎么完成隔离性的呢

例如上图:事务100、200、300、select1同时开启事务,事务100 和 事务200分别test表中 id = 1、id = 6的age赋值,这时候事务300开始修改account中id=1的balance加500,并且事务100、200都没提交,300提交了事务。

这时候其他事务 select1开始查询:

  1. 由于事务开启并且第一次开始查询语句的时候 事务 100、200都没有提交所以read-view为: (100,200),300
  2. 在开启事务 第一次查询语句才算是真正的开启事务,比如select1虽然和 100、200、300一起开启的事务,但是select1并没有任何操作,而这时id = 1的balance=0,事务id=300的将account中id=1的balance修改为加500时并且提交了,这时候select1再去执行查询才算是真正的开启了select1的事务,读取到的就是500.
  3. select1第一次开始查询undolog版本链id=1最新数据可以得到事务id = 300,此时并不在数组(100,200)的范围,代表是可读的。所以直接返回 balance = 500的数据
  4. 这时候事务 100 将id = 1的balance 第一次加了300第二次又加了200并且提交 这时候balance = 1000并且提交
  5. select1再次查询id = 1的数据发现balance =500而不是1000。是因为查询undo日志链最新的数据得到事务id = 100、balance = 10000在read-view的数组(100,200)中,不可见所以就会继续给上找,发现还是事务id=100、balance = 800 而事务id = 100还是在数组(100,200)之间,继续给上边找发现是 事务id = 300、balance = 500 不在数组之间,是可见的,返回balance = 500.

  1. 如果 这时候select1 再去修改id = 1的数据balance加100.那么select1再次查询会发现之前查询一直都是500这时候竟然变为了1100 。 原因就是事务对于查询是读取历史版本,而对于修改是修改当前提交数据,也就是虽然读取的是历史数据balance=500。但是修改却是最新提交数据1000进行处理的。并且将修改的数据放到内存中,下次这个事务读取这个数据就直接给内存中拿,也就是balance=1100了。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

消除噪音:Chain-of-Note (CoN) 强大的方法为您的 RAG 管道提供强大动力

论文地址&#xff1a;https://arxiv.org/abs/2311.09210 英文原文地址&#xff1a;https://praveengovindaraj.com/cutting-through-the-noise-chain-of-notes-con-robust-approach-to-super-power-your-rag-pipelines-0df5f1ce7952 在快速发展的人工智能和机器学习领域&#x…

HackTheBox - Medium - Linux - BackendTwo

BackendTwo BackendTwo在脆弱的web api上通过任意文件读取、热重载的uvicorn从而访问目标&#xff0c;之后再通过猜单词小游戏获得root 外部信息收集 端口扫描 循例nmap Web枚举 feroxbuster扫目录 /api/v1列举了两个节点 /api/v1/user/1 扫user可以继续发现login和singup 注…

(已解决)阿里云ECS服务器8080端口无法访问

最近购买阿里云服务器项目部署的时候&#xff0c;配置开放了阿里云8080端口&#xff0c;却一直访问不了&#xff0c;看了阿里云社区几个帖子&#xff0c;都没有找到正确的解决方法。 然后CSDN看了几个帖子&#xff0c;方法也不对。 索性&#xff0c;我很早之前就使用阿里云EC…

【JSON2WEB】01 WEB管理信息系统架构设计

WEB管理信息系统分三层设计&#xff0c;分别为DataBase数据库、REST2SQL后端、JSON2WEB前端&#xff0c;三层都可以单独部署。 1 DataBase数据库 数据库根据需要选型即可&#xff0c;不需要自己设计开发&#xff0c;一般管理信息系统都选关系数据库&#xff0c;比如Oracle、…

二维旋转公式推导+旋转椭圆的公式推导

二维旋转公式推导+旋转椭圆的公式推导 二维旋转公式推导旋转椭圆的公式推导二维旋转公式推导 x , y x,y x,y表示二维坐标系中原坐标点, x ′ , y ′ x,y x′,y′表示逆时针旋转 β \beta β之后的坐标点: x ′ = x cos ⁡ ( β ) − y sin ⁡ ( β ) y ′ = y cos ⁡ ( β )…

(循环依赖问题)学习spring的第九天

Bean实例的属性填充 Spring在属性注入时 , 分为如下几种情况 : 注入单向对象引用 : 如usersevice里注入userdao , userdao里没有注入其他属性 注入双向对象引用 : 如usersevice里注入userdao , userdao也注入usersevice属性 二 . 着重看循环依赖问题 (搞清原理即可) 问题提出…

RS-485通讯

RS-485通讯协议简介 与CAN类似&#xff0c;RS-485是一种工业控制环境中常用的通讯协议&#xff0c;它具有抗干扰能力强、传输距离远的特点。RS-485通讯协议由RS-232协议改进而来&#xff0c;协议层不变&#xff0c;只是改进了物理层&#xff0c;因而保留了串口通讯协议应用简单…

TypeScript教程(一)在vscode中的配置TypeScript环境

TypeScript教程&#xff08;一&#xff09;在vscode中的配置TypeScript环境 文章目录 TypeScript教程&#xff08;一&#xff09;在vscode中的配置TypeScript环境一、前言二、具体步骤1、Node.js安装2、TypeScript安装3、helloworld 一、前言 未来的开发者们请上座&#xff0c…

ChatQA实现策略:兼看大模型进行时序事件挖掘的思路

一、ChatQA&#xff1a;两阶段指令微调的对话思路 《ChatQA: Building GPT-4 Level Conversational QA Models》(https://arxiv.org/pdf/2401.10225.pdf)提出了一个两阶段的对话问答思路。 1、指令微调 微调包含两个阶段&#xff0c;Supervised Fine-tuning和Context-Enhanc…

Cortex-M3/M4内核NVIC及HAL库函数详解(2):HAL库中断底层函数实现

0 工具准备 Keil uVision5 Cortex M3权威指南&#xff08;中文&#xff09; Cortex M3与M4权威指南 stm32f407的HAL库工程 STM32F4xx中文参考手册 1 HAL库中断底层函数实现 打开stm32f407的HAL库工程&#xff0c;可以在CMSIS->Include->core_cm4.h内找到有关NVIC寄存器设…

ctfshow信息收集(web1-web20)

目录 web1 web2 web3 web4 web5 web6 web7 web9 web10 web11 web14 web15 web16 web17 web18 web19 web20 web1 根据提示的孩子开发的时候注释没有被及时删除 web2 js原因无法查看源代码 第一种方法 在url前加入 view-source&#xff1a; 会显示页面源代…

【LeetCode: 295. 数据流的中位数 + 堆】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

Windows如何给已经启动的Docker容器添加或者修改端口映射(通过修改配置文件实现)

需求&#xff1a;已经启动的Docker容器添加或者修改端口映射 找到配置文件&#xff1a; \wsl.localhost\docker-desktop-data*data*\docker\containers[hash_of_the_container] 有些版本在&#xff1a; \wsl$\docker-desktop-data*version-pack-data*\community\docker\contai…

Lambda支持的方法引用

目录 引用类中的静态方法替换lambda引用对象实例化方法替换lambda引用类中的实例方法替换lambda引用构造器替换lambda 引用类中的静态方法替换lambda 引用类方法&#xff1a;引用类的静态方法&#xff1b;类名::静态方法名 demo: 将String类型数据转换成为Integer类型 创建一个…

HCIA-HarmonyOS设备开发认证-序

序 最近涉及到HarmonyOS鸿蒙系统设备开发&#xff0c;在网络上已经有很多相关资料&#xff0c;视频教程&#xff0c;我也移植了公司的一个stm32G474板卡&#xff0c;运行LiteOS-m L0系统。 一面看资料一面移植&#xff0c;遇到不少坑&#xff0c;当看到运行的LOGO时&#xff0…

制冷培训一

常用制冷方法 1 相变制冷&#xff1a;汽液、液固 2 气体膨胀制冷&#xff1a;节流膨胀、膨胀机膨胀 3 半导体制冷&#xff1a; 4 涡流管制冷&#xff1a; 5 磁制冷&#xff1a; 6 稀释制冷&#xff1a; 7 激光制冷&#xff1a; 汽液相变制冷 1 蒸汽压缩制冷 2 蒸汽吸收制冷 3 …

大创项目推荐 深度学习验证码识别 - 机器视觉 python opencv

文章目录 0 前言1 项目简介2 验证码识别步骤2.1 灰度处理&二值化2.2 去除边框2.3 图像降噪2.4 字符切割2.5 识别 3 基于tensorflow的验证码识别3.1 数据集3.2 基于tf的神经网络训练代码 4 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x…

C++参悟:正则表达式库regex(更新中)

正则表达式库regex&#xff08;更新中&#xff09; 一、概述二、快速上手Demo1. 查找字符串2. 匹配字符串3. 替换字符串 三、类关系梳理1. 主类1. basic_regex 2. 算法3. 迭代器4. 异常5. 特征6. 常量1. syntax_option_type2. match_flag_type3. error_type 一、概述 C标准库为…

软件测试技术之【自动化测试】

自动化测试 自动化测试的定义&#xff1a;使用一种自动化测试工具来验证各种软件测试的需求&#xff0c;它包括测试活动的管理与实施、测试脚本的开发与执行。 自动化测试只是测试工作的一部分&#xff0c;是对手工测试的一种补充; 自动化测试绝不能代替手工测试;多数情况下&a…

自动控制原理——数学模型建立

目标 1.数学模型概念 描述系统输入、输出变量以及内部个变量之间的关系的数学表达式 2.建模方法 解析法&#xff08;机理解析法&#xff09;: 根据系统工作所依据的物理定律写运动方程 实验法&#xff08;系统辨识法&#xff09;&#xff1a; 给系统施加某种测试信号&am…