mysql 行锁,间隙锁,临键锁,锁范围和死锁实际例子实战

文章目录

    • 背景
    • 锁介绍
    • 默认数据
    • 测试
      • 唯一键记录存在
        • 事务1
        • 事务2
        • 结论
      • 唯一键记录不存在
        • 事务1
        • 事务2
        • 结论
      • 范围查询
        • 事务1
        • 事务2
        • 结论
      • 普通索引存在
        • 事务1
        • 事务2
        • 总结
      • 普通索引不存在
        • 事务A
        • 事务B
        • 结论
    • 死锁例子

背景

想了解下RR事务如何防止幻读的,以及一个实际的死锁例子

锁介绍

行锁(Record Lock):
锁直接加在索引记录上面。通常来说就是锁一行
间隙锁(Gap Lock):
锁加在不存在的空闲空间,可以是两个索引记录之间,也可能是第一个索引记录之前或最后一个索引之后的空间。通常来说是锁区间,可以表示为()
临键锁 ( Next-Key Lock )
行锁与间隙锁组合起来用就叫做Next-Key Lock。 可以表示为[]



CREATE TABLE `user` (
  `id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `user_id` bigint DEFAULT NULL COMMENT '用户id',
  `mobile_num` bigint NOT NULL COMMENT '手机号',
  PRIMARY KEY (`id`),
  UNIQUE KEY `IDX_USER_ID` (`user_id`),
  KEY `IDX_MOBILE_NUM` (`mobile_num`)
) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb3 COMMENT='用户信息表';

默认数据

iduser_idnumber
113
555
888
999

每次测试后,回到这个状态

测试

下面测试都是在事务RR级别下的测试的,mysql 版本8.0

唯一键记录存在

事务1

START TRANSACTION;
select * from 
demo.`user`  where id=5 for update
//先不提交
COMMIT;

查看锁信息

ENGINEENGINE_LOCK_IDENGINE_TRANSACTION_IDTHREAD_IDEVENT_IDOBJECT_SCHEMAOBJECT_NAMEPARTITION_NAMESUBPARTITION_NAMEINDEX_NAMEOBJECT_INSTANCE_BEGINLOCK_TYPELOCK_MODELOCK_STATUSLOCK_DATA
INNODB281473638589224:1068:28147356749102418566019demouser281473567491024TABLEIXGRANTED
INNODB281473638589224:2:4:5:28147356748811218566019demouserPRIMARY281473567488112RECORDX,REC_NOT_GAPGRANTED5
事务2
失败
update demo.`user` set user_id =5 where id=5;
成功
insert demo.`user` values(4,4,4)
成功
insert demo.`user` values(6,6,6)
结论

只会锁id=5这一行

唯一键记录不存在

事务1

START TRANSACTION;
select * from 
demo.`user`  where id=6 for update
COMMIT;
事务2
成功
insert demo.`user` values(4,4,4)
失败
insert demo.`user` values(5,5,5)
失败
insert demo.`user` values(6,6,6)
失败
insert demo.`user` values(7,7,7)
ENGINEENGINE_LOCK_IDENGINE_TRANSACTION_IDTHREAD_IDEVENT_IDOBJECT_SCHEMAOBJECT_NAMEPARTITION_NAMESUBPARTITION_NAMEINDEX_NAMEOBJECT_INSTANCE_BEGINLOCK_TYPELOCK_MODELOCK_STATUSLOCK_DATA
INNODB281473638589224:1068:28147356749102418756033demouser281473567491024TABLEIXGRANTED
INNODB281473638589224:2:4:6:28147356748811218756033demouserPRIMARY281473567488112RECORDX,GAPGRANTED8
结论

事务A锁住的区间是[6,7],从结果来推导一下,因为id=6这条记录不存在,所以在(5,8)的 间隙都要锁住,因为这些间隙都可能会插入ID=6

范围查询

事务1

START TRANSACTION;
select * from 
demo.`user`  where id>=5 and id<=8 for update
COMMIT;
ENGINEENGINE_LOCK_IDENGINE_TRANSACTION_IDTHREAD_IDEVENT_IDOBJECT_SCHEMAOBJECT_NAMEPARTITION_NAMESUBPARTITION_NAMEINDEX_NAMEOBJECT_INSTANCE_BEGINLOCK_TYPELOCK_MODELOCK_STATUSLOCK_DATA
INNODB281473638589224:1068:281473567491024195260110demouser281473567491024TABLEIXGRANTED
INNODB281473638589224:2:4:5:281473567488112195260110demouserPRIMARY281473567488112RECORDX,REC_NOT_GAPGRANTED5
INNODB281473638589224:2:4:6:281473567488456195260110demouserPRIMARY281473567488456RECORDXGRANTED8
事务2
成功
insert demo.`user` values(4,4,2)
都失败
insert demo.`user` values(5,5,3)
insert demo.`user` values(6,6,4)
insert demo.`user` values(7,7,5)
insert demo.`user` values(8,8,6)
成功
insert demo.`user` values(10,10,7)
结论

比较好理解,会把[5,8]都锁住

普通索引存在

事务1
START TRANSACTION;

select * from 
demo.`user`  where mobile_num=5 for update
COMMIT;
ENGINEENGINE_LOCK_IDENGINE_TRANSACTION_IDTHREAD_IDEVENT_IDOBJECT_SCHEMAOBJECT_NAMEPARTITION_NAMESUBPARTITION_NAMEINDEX_NAMEOBJECT_INSTANCE_BEGINLOCK_TYPELOCK_MODELOCK_STATUSLOCK_DATA
INNODB281473638589224:1068:28147356749102418916066demouser281473567491024TABLEIXGRANTED
INNODB281473638589224:2:6:7:28147356748811218916066demouserIDX_MOBILE_NUM281473567488112RECORDXGRANTED5, 5
INNODB281473638589224:2:4:5:28147356748845618916066demouserPRIMARY281473567488456RECORDX,REC_NOT_GAPGRANTED5
INNODB281473638589224:2:6:6:28147356748880018916066demouserIDX_MOBILE_NUM281473567488800RECORDX,GAPGRANTED8, 8
事务2
失败
update demo.`user` set user_id =5 where id=5;

都失败
insert demo.`user` values(10,10,3)
insert demo.`user` values(10,10,4)
insert demo.`user` values(10,10,5)
insert demo.`user` values(10,10,6)
insert demo.`user` values(10,10,7)

成功
insert demo.`user` values(10,10,8)
成功
insert demo.`user` values(10,10,2)
总结

where id=5 会把id=5锁,
set user_id =5 从数据来看,user_id从3到8的区间都可能插入5,所以user_id锁住的区间是(3,8)

普通索引不存在

事务A

START TRANSACTION;

select * from 
demo.`user`  where mobile_num =6 for update


COMMIT;
ENGINEENGINE_LOCK_IDENGINE_TRANSACTION_IDTHREAD_IDEVENT_IDOBJECT_SCHEMAOBJECT_NAMEPARTITION_NAMESUBPARTITION_NAMEINDEX_NAMEOBJECT_INSTANCE_BEGINLOCK_TYPELOCK_MODELOCK_STATUSLOCK_DATA
INNODB281473638589224:1068:28147356749102419106084demouser281473567491024TABLEIXGRANTED
INNODB281473638589224:2:6:6:28147356748811219106084demouserIDX_MOBILE_NUM281473567488112RECORDX,GAPGRANTED8, 8
事务B
成功
insert demo.`user` values(11,11,4)
失败
insert demo.`user` values(12,12,5)
失败
insert demo.`user` values(10,10,6)
失败
insert demo.`user` values(10,10,7)
成功
insert demo.`user` values(10,10,8)
结论

锁住了【5,8) ,因为6不存在,所以6可能在的区间是(5,8),这里为啥实际上把5锁住了,有点奇怪

死锁例子

事务A事务B
START TRANSACTION;
START TRANSACTION;
select * from demo.user where id=6 for update
select * from demo.user where id=7 for update
insert demo.user values(6,6,6)
insert demo.user values(7,7,7),然后报死锁

从之前的结论可以分析,5,8这个区间是空的,所以执行for update 操作会把这个区间锁住,两个事务都会对这加锁

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

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

相关文章

SnapGene Mac激活版 分子生物学软件

SnapGene Mac是一款功能全面、操作便捷的综合性分子生物学软件&#xff0c;专为Mac用户打造。它集成了DNA序列编辑、分析、可视化和团队协作等多种功能&#xff0c;为科研人员提供了一个高效、可靠的分子生物学研究工具。 SnapGene Mac激活版下载 在SnapGene Mac中&#xff0c;…

【Hadoop大数据技术】——Sqoop数据迁移(学习笔记)

&#x1f4d6; 前言&#xff1a;在实际开发中&#xff0c;有时候需要将HDFS或Hive上的数据导出到传统关系型数据库中&#xff08;如MySQL、Oracle等&#xff09;&#xff0c;或者将传统关系型数据库中的数据导入到HDFS或Hive上&#xff0c;如果通过人工手动进行数据迁移的话&am…

美容预约小程序:简单三步,开启高效预约模式

在当今的数字化时代&#xff0c;一个小程序可以极大地提高美容院的效率和客户满意度。下面我们将详细说明如何通过以下步骤来搭建一个美容院预约小程序。 首先&#xff0c;你需要注册并登录到乔拓云网&#xff0c;这是 一个在线平台&#xff0c;可以帮助你快速创建并管理你的小…

Kafka集群搭建可视化指南

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 Kafka集群搭建可视化指南 前言准备工作硬件要求环境准备 kafka集群的部署与配置3.1 单节点部署与多节点集群搭建单节点部署&#xff1a;多节点集群搭建&#xff1a; 3.2 Broker配置与优化3.3 Topic的创…

快速访问github

修改本地hosts文件 GitHub访问慢的原因在于域名解析&#xff0c;通过修改本地的hosts文件&#xff0c;将远程DNS解析改为本地DNS解析。 fang 步骤1&#xff1a;打开hosts文件&#xff08;没有就创建&#xff09; host所在位置&#xff1a; C:\Windows\System32\drivers\etc…

销售经理(多继承/虚基类)

根据下图类之间的继承关系&#xff0c;以及main和输出定义&#xff0c;定义Staff类、Saleman类、Manager类和SaleManager类。 Staff类包含的数据成员有编号&#xff08;num)&#xff0c;姓名&#xff08;name)&#xff0c;基本工资&#xff08;basicSale&#xff09;。Saleman类…

[lesson42]类型转换函数(下)

类型转换函数(下) 类型转换函数 C类中可以定义类型转换函数 类型转换函数用于将类对象转换成其他类型 语法规则&#xff1a; 类型转换函数 与转换构造函数具有同等的地位使得编译器有能力将对象转换为其他类型编译器能够隐式的使用类型转换函数 无法抑制隐式的类型转换函…

项目实践:贪吃蛇

引言 贪吃蛇作为一项经典的游戏&#xff0c;想必大家应该玩过。贪吃蛇所涉及的知识也不是很难&#xff0c;涉及到一些C语言函数、枚举、结构体、动态内存管理、预处理指令、链表、Win32 API等。这里我会介绍贪吃蛇的一些思路。以及源代码也会给大家放到文章末尾。 我们最终的…

二维码门楼牌管理应用平台建设:取保候审的智能化监管

文章目录 前言一、取保候审的传统监管困境二、二维码门楼牌管理应用平台的优势三、取保候审备案信息的智能化处理四、保障居民合法权益五、展望未来 前言 随着信息技术的飞速发展&#xff0c;二维码门楼牌管理应用平台已成为现代社区治理的重要工具。本文重点探讨如何借助该平…

Vue【路由】

1&#xff1a;什么是单页应用程序&#xff08;single page application&#xff09; 所有得功能在一个html页面上实现 2&#xff1a;单页面应用程序的优缺点 优点&#xff1a;按需更新性能高&#xff0c;开发效率也高&#xff0c;用户的体验较好 缺点&#xff1a;学习成本高…

卷王问卷考试系统/SurveyKing调查系统源码

SurveyKing是一个功能强大的开源调查问卷和考试系统&#xff0c;它能够快速部署并适用于各个行业。 这个系统提供了在线表单设计、数据收集、统计和分析等功能&#xff0c;支持20多种题型&#xff0c;提供多种创建问卷的方式和设置。 项 目 地 址 &#xff1a; runruncode.c…

JavaFX--基础简介(1)

一、介绍 中文官网&#xff1a;JavaFX中文官方网站OpenJFX 是一个开源项目,用于桌面、移动端和嵌入式系统的下一代客户端应用程序平台。openjfx.cn是OpenJFX(JavaFX)的标准中文翻译网站&#xff0c;致力于方便开发者阅读官方文档和教程。https://openjfx.cn/ JavaFX 是一个开…

2024第八届图像、信号处理和通信国际会议 (ICISPC 2024)即将召开!

2024第八届图像、信号处理和通信国际会议 &#xff08;ICISPC 2024&#xff09;将于2024年7月19-21日在日本福冈举行。启迪思维&#xff0c;引领未来&#xff0c;ICISPC 2024的召开&#xff0c;旨在全球专家学者共襄盛举&#xff0c;聚焦图像信号&#xff0c;在图像中寻找美&am…

袁庭新ES系列15节|Elasticsearch客户端基础操作

前言 上一章节我们介绍了搭建Elasticsearch集群相关的知识。那么又该如何来操作Elasticsearch集群呢&#xff1f;在ES官网中提供了各种语言的客户端&#xff0c;我们在项目开发过程中有多种Elasticsearch版本和连接客户端可以选择&#xff0c;那么他们有什么区别&#xff1f;这…

uniapp Android 插件开发教程

一、下载uniapp提供的SDK Android 离线SDK - 正式版 | uni小程序SDK 二、在uniapp创建一个项目 查看包名&#xff1a;发行--> 原生app 云打包 三、进入dcloud官网 开发者中心 进入 应用管理 --> 我的应用 --> 点击应用名称-->各平台信息-->新增 这里需要这…

【可视化大屏开发】19. 加餐-百度地图API实现导航加线路热力图

需求 Web端使用场景中会涉及到地图导航路线情况&#xff0c;并利用热力图显示路况信息。 实现效果如下&#xff1a; 输入起始地点&#xff0c;选择并开始导航 最终效果 思路步骤 利用百度地图API显示地图交通拥堵情况的热力图&#xff0c;需要按照以下步骤进行开发 步骤1&a…

面试被问懵了:手撕 Transformer

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对算法岗技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何准备、面试常考点分享等热门话题进行了深入的讨论。 今年最大…

Vue入门篇:概念,快速入门,插值表达式,核心特性,基本Vue指令

目录 1.Vue是什么2.快速入门3.插值表达式{{}}1.作用:2.语法:3.插值表达式的注意点: 4.Vue响应式核心特性5.Vue指令 1.Vue是什么 Vue是一个流行的JavaScript框架&#xff0c;用于构建用户界面。它是一种用于构建单页面应用程序&#xff08;SPA&#xff09;的渐进式框架&#xff…

MySQL 列数据跨表拷贝,一句SQL快速将表A每条记录的某些字段拷贝到表B每条记录的某些字段(A、B表通过ID等字段对应)

文章目录 MySQL 列数据跨表拷贝&#xff0c;一句SQL快速将表A每条记录的某些字段拷贝到表B每条记录的某些字段&#xff08;A、B表通过ID等字段对应&#xff09;背景定义表填充测试数据跨表一 一对应拷贝列数据SQL参考资料 MySQL 列数据跨表拷贝&#xff0c;一句SQL快速将表A每条…

【C++】:函数重载,引用,内联函数,auto关键字,基于范围的for循环,nullptr关键字

目录 一&#xff0c;函数重载1.1 函数重载的定义1.1.1.形参的类型不同1.1.2参数的个数不同1.1.3.参数的顺序不同1.1.4.有一个是缺省参数构成重载。但是调用时存在歧义1.1.5.返回值不同&#xff0c;不构成重载。因为返回值可接收&#xff0c;可不接受&#xff0c;调用函数产生歧…
最新文章