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 updateCOMMIT;
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.mzph.cn/pingmian/1073.shtml

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

相关文章

【计算机网络】面经

1.TCP&UDP 1.1TCP与UDP的区别 TCP传输数据稳定可靠&#xff0c;适用于对网络通信质量要求较高的场景。 面向连接。 每一条TCP有且只有两个端点&#xff0c;为一对一关系。 提供可靠交付。 全双工通信&#xff0c;全双工为即可传输又可接收。 面向字节流。 UDP的优点是速…

客户端动态降级系统

本文字数&#xff1a;4576字 预计阅读时间&#xff1a;20分钟 01 背景 无论是iOS还是Android系统的设备&#xff0c;在线上运行时受硬件、网络环境、代码质量等多方面因素影响&#xff0c;可能会导致性能问题&#xff0c;这一类问题有些在开发阶段是发现不了的。如何在线上始终…

微服务架构中的业务完整性验证设计

目录 1.概要设计 1.1 功能完整性与正确性验证 1.2 性能与响应速度验证 1.3 安全性验证 1.4 容错性与恢复能力验证 1.5 监控与日志记录验证 2.技术实现 2.1 测试策略与工具选择 2.2 身份验证与授权 2.3 数据一致性与事务管理 2.4 监控与日志 2.5 容错与恢复 2.6 数…

【linux kernel】 一文总结linux内核中的kobject、kset和ktype

文章目录 一、kobject、kset、ktype&#xff08;1-1&#xff09;kobject&#xff08;1-2&#xff09;ktype&#xff08;1-3&#xff09;kset 二、kobject操作API&#xff08;2-1&#xff09;kobject_init()&#xff08;2-2&#xff09;kobject_add()&#xff08;2-3&#xff09…

【命名空间详解】c++入门

目录 命名空间的定义 1.命名空间的正常定义 2.命名空间还可以嵌套 3. 命名空间可以合并 命名空间的使用 1.加命名空间名称及作用域限定符 2.使用using将命名空间中某个成员引入 3.使用using namespace 命名空间名称 引入 输入&#xff0c;输出 输出 命名空间的定义 …

linux命令ar使用说明

ar 建立或修改备存文件&#xff0c;或是从备存文件中抽取文件 补充说明 ar命令 是一个建立或修改备存文件&#xff0c;或是从备存文件中抽取文件的工具&#xff0c;ar可让您集合许多文件&#xff0c;成为单一的备存文件。在备存文件中&#xff0c;所有成员文件皆保有原来的属…

Java技术学习|Git

学习材料声明 尚硅谷Git入门到精通全套教程&#xff08;涵盖GitHub\Gitee码云\GitLab&#xff09; GIt Git 是一个免费的、开源的分布式版本控制系统&#xff0c;可以快速高效地处理从小型到大型的各种项目。Git 易于学习&#xff0c;占地面积小&#xff0c;性能极快。 它具有…

ARM_day8:基于iic总线的通信

一、IIC总线的基本概念&#xff1a; iic总线是一种带应答的同步的、串行、半双工的通信方式&#xff0c;支持一个主机对应多个从机。它有一根SCL&#xff08;时钟线&#xff09;和一根SDA&#xff08;数据线&#xff09;组成&#xff0c;由于只有一根数据线&#xff0c;所以它是…

英伟达大跳水!一夜暴跌10%,市值蒸发2000亿

相信大家已经在各大社交平台上看到了&#xff0c;英伟达一夜蒸发了2000亿美元&#xff01; GPT-3.5研究测试&#xff1a; https://hujiaoai.cn GPT-4研究测试&#xff1a; https://higpt4.cn Claude-3研究测试&#xff08;全面吊打GPT-4&#xff09;&#xff1a; https://hic…

大语言模型隐私防泄漏:差分隐私、参数高效化

大语言模型隐私防泄漏&#xff1a;差分隐私、参数高效化 写在最前面题目6&#xff1a;大语言模型隐私防泄漏Differentially Private Fine-tuning of Language Models其他初步和之前的基线微调模型1微调模型2通过低秩自适应进行微调&#xff08; 实例化元框架1&#xff09; 在隐…

Vue2 —— 学习(九)

目录 一、全局事件总线 &#xff08;一&#xff09;全局总线介绍 关系图 对图中的中间商 x 的要求 1.所有组件都能看到 2.有 $on $off $emit &#xff08;二&#xff09;案例 发送方 student 接收方 二、消息订阅和发布 &#xff08;一&#xff09;介绍 &#xff08…

虚拟机中的打印机,无法打印内容,打印的是白纸或英文和数字,打印不了中文

原因&#xff1a;打印机驱动设置不正确 解决方案&#xff1a; 打开打印机属性 -> 高级 -> 新驱动程序 下一页 -> Windows 更新 耐心等待&#xff0c;时间较长。 选择和打印机型号匹配的驱动&#xff0c;我选择的是&#xff1a; 虽然虚拟机和主机使用的驱动不…

跨境电商指南:防关联浏览器和云主机有什么区别?

跨境电商的卖家分为独立站卖家和平台卖家。前者会自己开设独立站点&#xff0c;比如通过 shopify&#xff1b;后者则是入驻亚马逊或 Tiktok 等平台&#xff0c;开设商铺。其中平台卖家为了扩大收益&#xff0c;往往不止开一个店铺&#xff0c;或者有店铺代运营的供应商&#xf…

皇后之战:揭秘N皇后问题的多维解法与智慧【python 力扣52题】

作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 欢迎加入社区&#xff1a;码上找工作 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 python数据分析…

Go之map详解

map的结构 map实现的两个关键数据结构 hmap 定义了map的结构bmap 定义了hmap.buckets中每个bucket的结构 // A header for a Go map. type hmap struct {count int // 元素的个数flags uint8 // 状态标记&#xff0c;标记map当前状态&#xff0c;是否正在写入B …

css层叠性,继承性,优先级

前言 本文概要&#xff1a;讲述css的三大特性&#xff0c;层叠&#xff0c;继承和优先级。 层叠性 描述&#xff1a;我们试想以下这种情况&#xff1a;我们定义了同一个选择器&#xff0c;但是定义的属性不同。属性有相同的也有不同的&#xff0c;那么最后我们这个页面会听谁的…

CSS display属性

目录 概述&#xff1a; 设置display示例&#xff1a; none&#xff1a; block&#xff1a; inline&#xff1a; inline-block &#xff1a; 概述&#xff1a; 在CSS中我们可以使用display属性来控制元素的布局&#xff0c;我们可以通过display来设置元素的类型。 在不设置…

封装个js分页插件

// 分页插件类 class PaginationPlugin {constructor(fetchDataURL, options {}) {this.fetchDataURL fetchDataURL;this.options {containerId: options.containerId || paginationContainer,dataSizeAttr: options.dataSizeAttr || toatalsize, // 修改为实际API返回的数据…

vue里面事件修饰符.prevent使用案例

什么是.prevent事件修饰符&#xff1f; 在Vue中&#xff0c;事件修饰符是指在事件处理函数后面添加的特殊标记&#xff0c;用于修改事件的行为。.prevent事件修饰符是其中之一&#xff0c;它的作用是阻止事件的默认行为。通常情况下&#xff0c;当用户触发某些事件时&#xff0…

ppt技巧:​如何将两个PPT幻灯片文件合并成一个?

第一种方式&#xff1a;复制粘贴幻灯片 1. 打开第一个PPT幻灯片文件&#xff0c;确保你已经熟悉该文件的内容和布局。 2. 打开第二个PPT幻灯片文件&#xff0c;浏览其中的所有幻灯片&#xff0c;选择你想要合并到第一个文件中的幻灯片。 3. 使用快捷键CtrlC&#xff08;Wind…