MySQL学习笔记(十五)行锁表锁间隙锁临键锁共享锁排他锁死锁

news2024/12/29 14:16:33

行锁表锁间隙锁临键锁共享锁排他锁死锁

  • 手动提交
  • 行锁(记录锁Record Locks)
  • 表锁
  • 间隙锁(Gap Locks)
  • 临键锁(Next-Key Locks)
  • 共享锁,排他锁
  • 死锁
    • 查看事物,锁的命令
    • 死锁的4个必要条件
    • 模拟死锁
    • 如何防止死锁

手动提交

在这里插入图片描述

//查看自动提交
show VARIABLES like 'autocommit';
//关闭自动提交,改为手动提交
set autocommit = 0;
CREATE table test_lock(
	id int(11) DEFAULT NULL,
	username varchar(32) DEFAULT NULL,
	age tinyint(4) DEFAULT NULL,
	KEY idx_id (id),
	KEY idx_name (username),
	KEY idx_age (age)
) ENGINE=INNODB DEFAULT CHARSET = utf8;

INSERT INTO `test_lock` (`id`, `username`, `age`) VALUES ('1', 'zhangsan', '11');
INSERT INTO `test_lock` (`id`, `username`, `age`) VALUES ('3', 'lisi', '22');
INSERT INTO `test_lock` (`id`, `username`, `age`) VALUES ('5', 'wangwu', '33');
INSERT INTO `test_lock` (`id`, `username`, `age`) VALUES ('7', 'chenqi', '44');
INSERT INTO `test_lock` (`id`, `username`, `age`) VALUES ('9', 'liuba', '55');

行锁(记录锁Record Locks)

首先新建一个查询窗口A,来修改一条数据并查询(注意此时并没有提交事物)

UPDATE test_lock SET username = 'huangshang' WHERE id = 1;
SELECT * from test_lock;

id = 1 的 username 已经修改为 huangshang
在这里插入图片描述

然后再新建一个查询窗口B,查询,此时查询到的id=1 的username 还是zhangsan

在这里插入图片描述
这是因为窗口A里面的事物并没有提交,当窗口执行commit后,窗口B的查询结果就是最新的数据

此时窗口A 和 窗口B同时执行修改操作(窗口A没有commit)

// 窗口A 把id=1的username 改为111
UPDATE test_lock SET username = '111' WHERE id = 1;

// 窗口B 把id=1的username 改为222
UPDATE test_lock SET username = '111' WHERE id = 1;

可以看到下图中,窗口A的修改执行完成,窗口B执行失败因为窗口A把id=1这行上锁了
在这里插入图片描述
如果窗口A commit之后会怎么样?
在这里插入图片描述
可以看到窗口Acommit之后,窗口B立马就执行成功了,因为commit之后窗口A的行锁就释放了,B就可以进行修改操作了

表锁

当行锁的索引失效就会升级为表锁,例如窗口A修改id=1 or id=2的数据,然后窗口B修改id=3的数据,如果按照行锁来处理的话,窗口B应该会执行成功的,因为窗口A会锁id = 1 和 2 的这2行数据,id=3的记录并没有上锁

// 窗口A
UPDATE test_lock SET username = '111' WHERE id = 1 or id = 2;
// 窗口B
UPDATE test_lock SET username = '222' WHERE id = 3;

如图窗口B是执行失败的,因为窗口A的sql索引失效,造成了表锁
在这里插入图片描述

只有当窗口Acommit之后 ,表锁释放,此时窗口B就可以执行成功了
在这里插入图片描述

间隙锁(Gap Locks)

先把表里面id改为 13579,中间的2468是没有的
在这里插入图片描述
此时窗口A执行修改操作,修改 1<id<9 的数据,那么此时1-9的行就会上锁
此时窗口B执行插入操作,因为id=4的记录并没有

// 窗口A
UPDATE test_lock SET username = '111' WHERE id > 1 or id < 9;

//窗口B
INSERT INTO test_lock (id, username) VALUES ('4', 'gaogao');

可以看到,窗口A的事物把1-9的记录 都上锁了,包过新增的id=4的记录,所以窗口B执行失败,这就是间隙锁
在这里插入图片描述

临键锁(Next-Key Locks)

在这里插入图片描述

如表所示,age列潜在的临键值有
(-∞, 11]
(11, 22]
(22, 33]
(33, 44]
(44, +∞]

现在窗口A执行修改,并排他锁读

-- 根据非唯一索引列age 修改姓名
UPDATE test_lock SET username = 'kkk' WHERE age = 22; 
-- 根据非唯一索引列age 锁住22这行记录 
SELECT * FROM test_lock WHERE age = 22 FOR UPDATE; 

然后窗口B执行插入操作

INSERT INTO test_lock (id, username, age) VALUES ('11', 'lisi', '25');

可以看到窗口B的插入操作被阻塞了,因为窗口A没有释放锁,锁住了age=22-33这个区间范围,导致窗口B在插入age=25的时候被阻塞了,这就是临键锁
在这里插入图片描述

关于记录锁,间隙锁,临键锁的区别

  • InnoDB 中的行锁的实现依赖于索引,一旦某个加锁操作没有使用到索引,那么该锁就会退化为表锁。
  • 记录锁存在于包括主键索引在内的唯一索引中,锁定单条索引记录。
  • 间隙锁存在于非唯一索引中,锁定开区间范围内的一段间隔,它是基于临键锁实现的。
  • 临键锁存在于非唯一索引中,该类型的每条记录的索引上都存在这种锁,它是一种特殊的间隙锁,锁定一段左开右闭的索引区间。

共享锁,排他锁

// 共享锁(S)
select * from test_lock where id = 1 lock in share mode
// 排他锁(X)
select * from test_lock where id = 1 for update
  • 共享锁:不会阻塞其他事务对同一行的读请求,但会阻塞对同一行的写请求。只有当读锁释放后,才会执行其它事物的写操作。
  • 排他锁:会阻塞其他事务对同一行的读和写操作,只有当写锁释放后,才会执行其它事务的读写操作。

如图窗口A使用的共享锁,窗口B可以正常读操作
在这里插入图片描述
如图窗口A使用的共享锁,窗口B写操作会阻塞,需要等A执行完成之后才能进行写操作
在这里插入图片描述
而对应排他锁来说,窗口A的sql如果加了排他锁,那么窗口B的读和写操作都会阻塞,需要等A释放锁之后才能操作

死锁

查看事物,锁的命令

//查看正在进行中的事务
SELECT * FROM information_schema.INNODB_TRX
//查看正在锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
//查看等待锁的事务
SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
//查询是否锁表
SHOW OPEN TABLES where In_use > 0;
//查看最近死锁的日志
show engine innodb status

在这里插入图片描述

死锁的4个必要条件

  • 互斥条件
  • 请求与保持条件
  • 不剥夺条件
  • 环路等待条件

模拟死锁

-- 窗口A修改age=22的姓名
begin;
UPDATE test_lock SET username = 'www' WHERE age = 22; 

-- 窗口B修改age=33的姓名
begin;
UPDATE test_lock SET username = 'qqq' WHERE age = 33; 

这2个操作都是行锁,互不干扰,都可以执行成功,注意这2个操作都没有提交

在这里插入图片描述
现在窗口A来修改age=33的记录,窗口B来修改age=22的记录
此时窗口A执行会阻塞等待窗口B age=33释放锁,如果此时窗口B也执行的话,就会造成死锁,因为它需要等窗口A的age=22释放锁,这样就形成了闭环,相互持有锁,都在等对方释放锁,就造成死锁了,此时MySQL会让窗口B的事物报错,同时释放窗口B的锁,这样窗口A就能正常执行了

在这里插入图片描述

如何防止死锁

  • 使用共享锁,可以防止在读取数据的过程中,其它事务对数据进行更新;其它事务可以并发读取数据
  • 使用排他锁,可以阻塞其他事物的读写操作
  • 避免并发修改同一条数据
  • 一个事物中的所有操作都必须加锁
  • 通过加锁顺序来控制事物的执行顺序
  • 一个事物的执行时间不能过长,如果有很多操作可以考虑进行拆分成多个事物
  • 使用尽可能低的隔离级别
  • 保证事物简短并在一个批处理当中执行

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

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

相关文章

odoo学习之security, menu, tree, form

security 在ir.model.access.csv中 id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink可以设置成 access_org_info,org.info,model_org_info,,1,1,1,1其中&#xff1a;access_org_info&#xff1a;access_为固定开头&#xff0c;org_info为模块…

Mol2Image: Improved Conditional Flow Models for Molecule to Image Synthesis

Mol2Image: 连接药物分子与细胞显微图像的条件流模型【2021CVPR】 Mol2Image: Improved Conditional Flow Models for Molecule to Image Synthesis paper&#xff1a;Improved Conditional Flow Models for Molecule to Image Synthesis | Papers With Code code&#xff1…

谷粒商城之高级篇(3)

2 商城业务 2.7 订单服务 2.7.22 创建业务交换机&队列 这里承接 知识补充篇 6 RabbitMQ 订单分布式主体逻辑 订单超时未支付触发订单过期状态修改与库存解锁 创建订单时消息会被发送至队列order.delay.queue&#xff0c;经过TTL的时间后消息会变成死信以order.release…

如何配置 SLO

前言 无论是对外提供 IaaS PaaS SaaS 的云公司&#xff0c;还是提供信息技术服务的乙方公司&#xff0c;亦或是金融 制造等各行各业的数据中心、运维部门&#xff0c;我们的一个非常重要的合同承诺或考核评估指标就是&#xff1a;SLA&#xff08;即&#xff1a;Service-Level …

蓝桥杯算法训练:FBI树(c++实现+图文详解)

文章目录FBI树C代码示例FBI树 题目要求 我们可以把由“0”和“1”组成的字符串分为三类&#xff1a;全“0”串称为B串&#xff0c;全“1”串称为I串&#xff0c;既含“0”又含“1”的串则称为F串。 FBI树是一种二叉树&#xff0c;它的结点类型也包括F结点&#xff0c;B结点和I…

某公司高管疾呼:底层程序员离职率太高,有人入职不到半年就走!建议把恶意离职加入征信,让年轻人对公司有起码的尊重!...

许多人入职后才发现公司有各种难以忍受的问题&#xff0c;入职时间很短就被迫离职&#xff0c;这本是无可奈何的事&#xff0c;但一位公司高管却对此非常愤怒&#xff0c;指出“目前基层程序员离职率太高&#xff0c;有人入职不到半年就走了”&#xff0c;还建议把恶意离职加入…

MVC开发模式

1、JSP演变历史 1、早期只有servlet&#xff0c;只能使用response输出标签数据&#xff0c;非常麻烦 2、后来又有了jsp&#xff0c;简化了Servlet的开发&#xff0c;但如果过度使用jsp&#xff0c;在jsp中即写大量的Java代码&#xff0c;又有HTML&#xff0c;会造成难以维护&am…

【红黑树】

红黑树红黑树的概念红黑树的性质红黑树结点的定义红黑树的插入红黑树的验证红黑树的查找红黑树与AVL树的比较红黑树的概念 红黑树是一种二叉搜索树&#xff0c;但在每个结点上增加了一个存储位用于表示结点的颜色&#xff0c;这个颜色可以是红色的&#xff0c;也可以是黑色的&a…

主存储器扩展技术(计组)

用已有的存储器芯片构造一个需要的存储空间。 位扩展–扩展字长 构成内存的存储器芯片的字长小于内存单元要求的字长时–需要进行位扩展。实例&#xff1a; 位扩展的连线特点&#xff1a; 将每片的地址线、控制线并联&#xff0c;数据线分别引出。 效果&#xff1a; 存…

JavaSE笔记——函数式编程(流)

文章目录前言一、从外部迭代到内部迭代二、实现机制三、常用的流操作1.collect(toList())2.map3.filter4.flatMap5.max和min6.reduce四、多次调用流操作五、高阶函数总结前言 流是一系列与特定存储机制无关的元素——实际上&#xff0c;流并没有 “存储” 之说。利用流&#x…

如何用python打造新年氛围组?【内含html源码赠送】

嗨害大家好鸭&#xff01;我是小熊猫~ 离正式过新年还有24天~ 这次给大家整一个花活~ 就是每时每秒都提醒离新年还有多久 我这里还有一些中国结的python代码&#xff0c; 大家可以文末名片自行领取鸭~ 倒计时 效果展示 有什么python相关报错解答自己不会的、或者源码资料/…

操作系统——计算机系统概述

操作系统——计算机系统概述一、操作系统的概念1、定义2、功能和目标二 、操作系统特征1、并发性2、共享性3、虚拟性4、异步性三、操作系统的发展1、手工操作阶段2、批处理阶段——单道批处理系统2、批处理阶段——多道批处理系统3、实时操作系统四、运行机制和体系结构1、运行…

EnvironmentAware 接口的使用

文章目录1、EnvironmentAware 接口作用2、实际应用3、代码演示1&#xff09;基本配置准备2&#xff09;增加属性配置文件 application.properties3&#xff09;增加配置类实现 EnvironmentAware 接口4、编写 main 方法的类 SpringTest.java5、运行 main 方法查看结果1、Environ…

Java之线程状态

目录一、简介二、线程状态1、新建状态&#xff08;New&#xff09;2、运行状态&#xff08;Runnable&#xff09;3、阻塞状态&#xff08;Blocked/Waiting/TimeWaiting&#xff09;&#xff08;1&#xff09;被阻塞状态&#xff08;Blocked&#xff09;&#xff08;2&#xff0…

新新新~Revit插件【建模助手】7大模块介绍

年底了&#xff0c;大家是不是都在喝茶、聊天、等跨年&#xff1b;而我&#xff0c;建模助手&#xff0c;则在——总结、规划、PPT。 不盘不知道&#xff0c;一盘可吓了我一大跳&#xff01;没想到咱们在过去一年居然建设了这么多丰功伟绩&#xff1a; 说点标志性的&#xff…

到底什么是电子管(真空管)?

1883年&#xff0c;著名发明家托马斯爱迪生&#xff08;Thomas Edison&#xff09;在一次实验中&#xff0c;观察到一种奇怪现象。当时&#xff0c;他正在进行灯丝&#xff08;碳丝&#xff09;的寿命测试。在灯丝旁边&#xff0c;他放置了一根铜丝&#xff0c;但铜丝并没有接在…

WebRTC系列-视频VideoBroadcaster与视频流

文章目录 1. VideoBroadcaster 添加sink2. VideoBroadcaster 视频数据分发OnFrame方法在前面的文章视频的采集流程中,视频数据采集完成后到编码器之前,如果需要渲染处理那里需要两路视频,WebRTC是实现了一个视频分发器VideoBroadcaster;用来分发采集的视频帧; 这篇文章主要…

Nginx网页配置工具nginxWebUI

今天应该是我们公司 2022 年最后一天上班了&#xff0c;给自己做个简单的年度总结吧&#xff1a; 1月&#xff1a;做核酸 2月&#xff1a;做核酸 3月&#xff1a;做核酸&#xff0c;半个月左右居家办公 4月&#xff1a;做核酸&#xff0c;静态管理 5月&#xff1a;做核酸&…

贪吃蛇基础·框架版(简单)开头有原码

更新不易&#xff0c;麻烦多多点赞&#xff0c;欢迎你的提问&#xff0c;感谢你的转发&#xff0c; 最后的最后&#xff0c;关注我&#xff0c;关注我&#xff0c;关注我&#xff0c;你会看到更多有趣的博客哦&#xff01;&#xff01;&#xff01; 喵喵喵&#xff0c;你对我…

XStream < 1.4.20 栈缓冲区溢出漏洞

漏洞描述 XStream 是一个轻量级的、简单易用的开源Java类库&#xff0c;它主要用于将对象序列化成XML&#xff08;JSON&#xff09;或反序列化为对象。 在1.4.20之前的版本中存在栈缓冲区溢出漏洞&#xff0c;从而导致通过操纵已处理的输入流来造成拒绝服务。 在使用集合和映…