Mysql的行锁,改一行锁一行

目录标题

  • 前言
  • 行级锁
    • 1. 共享锁(Shared Lock)
    • 2. 排他锁(Exclusive Lock)
  • 行级锁中的死锁(Dead Lock)现象
  • 行级锁虽好,但有时候会升级成表级锁
    • 第一种情况,当未命中索引时,行级锁会升级成表级锁。😢
    • 第二种情况,当更新所有数据时,会从行级锁升级成表级锁。😒
  • 总结😊

前言

在 MySQL 数据库中,提供锁机制这个功能的是存储引擎,如果需要使用行锁就必须使用支持行锁的存储引擎。在 MySQL 数据库中,MyISAM 存储引擎是不支持行级锁的,支持行锁的是 InnoDB 存储引擎,这也是 MySQL 数据库后来选择 InnoDB 存储引擎为默认存储引擎的原因之一。

行级锁的功能是跟表级锁类似,都是用来锁定数据的,用来防止并发导致数据修改失败这种情况的出现。所不同的是表锁是锁定整个表的数据,而行级锁是操作一行、锁定一行,并且行级锁也是 MySQL 中粒度最小的锁

当操作某个数据表中的数据使用表级锁时,整个数据表中所有的数据都会被锁定而无法操作,也就是同一时间只能有一个修改操作,这是非常影响数据库并发的,不适合访问量大的场景。而行级锁是操作一行、锁定一行,所以在最大程度上减少了数据表中多个操作之间的冲突,进而提升了数据库数据更新的并发。

行级锁

行级锁就是将修改一行、锁住一行。但这里有一点我们需要注意:行级锁是产生于一个事务之中的,当事务提交或者回滚之后,行级锁立即自动释放。

在 MySQL 数据库中行级锁主要有两种,分别是:共享锁与排他锁。

1. 共享锁(Shared Lock)

共享锁又称为读锁,也可以简称为:S 锁。添加共享锁的语句为:lock in share mode。当多个事务同一时间修改同一条数据时,共享锁只允许其中的一个事务修改数据,读数据则不限制。

通常情况下,共享锁的使用场景是保证数据库中数据与数据之间的关系。举个例子:我们在购物时,总是会让我们添加地址;在填写地址之时,首先会让我们选择省份,其次是市,最后是详细的地址。在这个场景中,如果我们需要添加浦东新区的话,就意味着上海市这个上级选项必须存在。假设,我们添加浦东新区时,恰好其他人把上海市删除;那此时,我们添加的浦东新区就失去了它的意义。

为了防止这个情况的发生,我们最好添加一个锁机制,这个锁机制既不影响数据库的正常读,又能保证数据关系一致。在这种场景下,我们正好用到共享锁。

下面我们利用上面填写地址的例子,来描述一下共享锁的使用场景。

步骤 1,在事务一中开启一个共享锁,在事务二中测试共享锁是否影响查询:

-- 在事务二中查询该条数据,发现添加了共享锁的数据仍然可以正常查询。
mysql> select * from province where id = 1;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | 上海市     |
+----+-----------+
1 row in set (0.08 sec)

在这里插入图片描述
可以看出,增加了共享锁之后,其他事务中该条数据是可以正常查询的。

步骤 2,当加上共享锁之后,添加浦东新区,同时删除上海市:

在事务1中增加共享锁,同时增加一条数据

mysql> insert into city (name, fid) values (‘浦东新区’, 1); Query OK, 1 row affected (0.00 sec)

在事务2中删除一条数据

mysql> delete from province where id = 1; ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

在这里插入图片描述
我们可以看到,当一个事务中增加了共享锁之后,上海市这条数据无法删除,并且处于阻塞状态。

注意:长时间不处理数据库阻塞时,会报一个ERROR 1205 (HY000): Lock wait timeout exceeded;
try restarting transaction的错误,这是因为阻塞超时了。

在 MySQL数据库中,锁机制阻塞的超时时间受innodb_lock_wait_timeout的影响,我们可以以下语句来临时修改锁机制阻塞的时间:SET GLOBAL innodb_lock_wait_timeout=100;,单位秒(s)。

综上,我们可以得出,共享锁的主要功能是:在某个事务中某条数据只要加上了共享锁,那么对于其他的事务来说该条数据将可读但是无法修改。

现在你知道为什么添加上共享锁之后,该条数据就无法正常修改了吧?接下来,我们再一起来探讨一下另一种行级锁——排他锁。

2. 排他锁(Exclusive Lock)

排他锁又称为写锁,也可以简称为:X 锁。在某个事务中给某些数据添加了排他锁,那么这部分数据将无法添加其他锁机制。添加排他锁的语句是:for update。

排他锁和共享锁一样,是需要在事务中开启,当事务提交或者回滚之后将自动释放。另外,还需要注意的是,在一个事务中一个更新的操作会自动添加排他锁。

为了更好地理解排他锁,这里我还是给你举个例子。

春运时,我们需要购买从上海到北京的车票,你跟另一个朋友同时抢购上海到北京的车票,恰好这个时候只剩下一张车票(每购买一张车票之后,剩余的车票数减 1)。假设我们在不考虑并发(同时修改同一条数据就称为并发)的情况下,如果两个人同时抢票就会把原来剩下的 1 修改成 -1,这个时候就会出现重复购票这种情况。

为了防止这种情况的发生,在购买车票时,可以采用 MySQL 数据库为我们提供的锁机制。如果采用表锁,将会将整个表中的所有数据全部锁定,此时除了该车次的车票无法购买之外,其他所有车次的车票全部无法购买,很大程度上影响购买的速度。所以,MySQL 又为我们提供了一个行级锁,当我们购买哪一个车次的车票就会锁定该车次的车票数据,这样做既保证安全又降低了复杂度。

下面我用具体的案例来帮助你理解下。

步骤 1,开启两个事务,来测试排他锁,开启事务的 SQL 参考上面,这里就不再重复列举。
步骤 2,修改票数:
查看火车票上海至北京的票数为1(该表数据只适合用来模拟排他锁的场景)

mysql> select * from train_tickets; 
+——+————————-+———+ | id | tickets | num | 
+——+————————-+———+ | 1 | 上海至北京 | 1 | 
+——+————————-+———+ | 1 row in set (0.00 sec)

修改票数

mysql> update train_tickets set num=num-1 where id = 1; 
Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0

在这里插入图片描述

根据上面的案例,我们可以看出两个事务同时修改同一条数据只能有一个修改成功,这也就保证了数据的安全性。

此时,我们假设一下,如果两个事务同时包含了对方所需要的锁,会有什么效果呢?我们接着往下看。

行级锁中的死锁(Dead Lock)现象

死锁,并不是 MySQL 数据库提供的一种锁机制,而是在使用 MySQL 数据库锁机制的过程中出现的因争夺锁资源而导致一直处于等待阻塞状态的一种错误现象。表锁是不可能出现死锁现象的,死锁只产生于行锁之间。

为了方便理解死锁,我还是通过一个例子来讲解。

步骤 1,事务 1 修改 info 表中 id 为 1 的这条数据,事务 2 修改 info 表中 id 为 3 的这条数据:

事务1中修改id为1的这条数据

mysql> update info set name = ‘女神’ where id = 1; 
Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0

事务2中修改id为3的这条数据

mysql> update info set name = ‘翠花妹妹’ where id = 3; 
Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0

步骤 2,事务 1 修改 info 表中 id 为 3 的这条数据,事务 2 中修改 info 表中 id 为 1 的这条数据:

事务1中修改info表中id为3这条数据

mysql> update info set name = ‘铁锤妹妹’ where id = 3; 
Query OK, 0 rows affected (22.91 sec) Rows matched: 1 Changed: 0 Warnings: 0

事务2中修改info表中id为1这条数据(报错)

mysql> update info set name = ‘翠花’ where id = 1; 
ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

如下图
在这里插入图片描述

此时,就造成了一种事务交叉,进而造成了死锁现象。如下图:
在这里插入图片描述

因此,在实际应用过程中,当需要多个锁时,要尽可能地把那些可能引发锁冲突的锁进行拆分或者往后放,进而最大限度地避免锁冲突举个例子:在马路上经过十字路口时,如果没有红绿灯,很快就会堵死;为了解决这个问题,红绿灯让一部分车提前,一部分稍微延后一点行驶即可。死锁也是这样,既然有冲突,就让一部分锁先执行,等这部分执行完毕之后,另一部分后执行,就可以避免这个错误了

行级锁虽好,但有时候会升级成表级锁

在实际应用中,有些情况下行级锁会升级成为表级锁,进而导致数据库的并发能力下降。那具体哪些情况下会升级为表级锁呢?

第一种情况,当未命中索引时,行级锁会升级成表级锁。😢

-- 在事务1中不使用索引查询数据时,加排他锁(行级锁)
mysql> select * from info where name like '%xxx%' for update;
Empty set (0.00 sec)
-- 在事务2中查询数据时,也加排他锁,发现无法查询
mysql> select * from info where id = 2 for update ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

在这里插入图片描述

根据上面案例,我们可以得出:在未使用索引的情况下,使用行锁会引发表锁,这是因为在 MySQL 数据库中行级锁并不是直接锁每一行的数据,而是锁字段的索引

在 MySQL 数据库中有两种索引,分别是:主键索引和非主键索引。当一条 SQL 使用主键索引时,会直接在主键索引上增加锁;而当一条 SQL 使用非主键索引时,会首先通过非主键索引找到数据表中的主键索引,然后再给主键索引加锁

第二种情况,当更新所有数据时,会从行级锁升级成表级锁。😒

在实际应用过程中,在一个数据量比较小的表中更新大量数据时,行锁会升级成为表锁。示例如下:

-- 在事务1中更新所有的数据。
mysql> update city set fid = 2;
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0
-- 在事务2中随机找一个数据加排他锁,发现无法添加。
mysql> select * from city where id = 1 for update ;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

在这里插入图片描述

总结😊

  • 共享锁主要是用来解决数据一致性问题的。加上共享锁之后,该条数据在其他事务中只读但不可以修改。
  • 排他锁就像它的名字一样,排斥其他的锁机制,也就是说加上排他锁之后,将无法再添加任何其他锁。

这样就保证了在大量的数据并发情况下不会出现重复修改这种情况,而且行级锁是操作一行锁定一行的,解决了表级锁锁住数据太多而导致的并发问题。

但在实际的应用中,并不是加的锁越多越好。加锁和释放锁都是有时间消耗的,例如行锁,更新一行加一行的锁,是会很消耗性能的,会很慢的。所以,要尽量避免大量更新数据的情况

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们处理,核实后本网站将在24小时内删除侵权内容。

在这里插入图片描述

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

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

相关文章

十五 MyBatis的逆向工程

十五、MyBatis的逆向工程 所谓的逆向工程是:根据数据库表逆向生成Java的pojo类,SqlMapper.xml文件,以及Mapper接口类等。 要完成这个工作,需要借助别人写好的逆向工程插件。 思考:使用这个插件的话,需要…

易快报与金蝶云星空无缝集成的技术实现

易快报与金蝶云星空无缝集成的技术实现 易快报员工对接金蝶员工:数据集成技术案例分享 在企业信息化建设中,数据的高效流动和准确对接是实现业务流程自动化的关键。本文将聚焦于一个具体的系统对接集成案例——易快报员工数据集成到金蝶云星空&#xff…

day-81 排序链表

思路 用一个List存储链表中的值,然后进行升序排序,最后将链表中值依次改为排序后的值即可 Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { …

【零基础小白】 window环境下安装RabbitMQ

RabbitMQ环境安装 RabbitMQ是用Erlang语言编写的,因此在安装RabbitMQ之前,需要先安装Erlang环境。 一、 安装Erlang环境 1、准备工作 确定Erlang版本:根据具体需求以及必须和RabbitMQ版本一致安装符合的Erlang版本。 RabbitMQ 和 Erlang 的版…

【MySQL系列】区分大小写与支持表情字符的考量

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

【科普】简述机器学习和深度学习及其相关的算法

文章目录 机器学习1. 基本概念2. 机器学习的分类3. 机器学习的常用方法4. 应用领域5. 挑战与未来6. 未来趋势 机器学习算法 深度学习1.深度学习的基本概念2.深度学习的主要架构3.深度学习的应用4.深度学习的挑战 深度学习算法 机器学习 机器学习是人工智能的一个重要分支&…

232转485模块测试

概述 常用的PLC一般会有两个左右的232口,以及两个左右的485口,CAN口等,但是PLC一般控制的设备可能会有很多,会超出通讯口的数量,此时我们一般会采用一个口接多个设备,这种情况下要注意干扰等因素&#xff0…

STM32外设之SPI的介绍

### STM32外设之SPI的介绍 SPI(Serial Peripheral Interface)是一种高速的,全双工,同步的通信总线,主要用于EEPROM、FLASH、实时时钟、AD转换器等外设的通信。SPI通信只需要四根线,节约了芯片的管脚&#x…

LLM——10个大型语言模型(LLM)常见面试题以及答案解析

今天我们来总结以下大型语言模型面试中常问的问题 1、哪种技术有助于减轻基于提示的学习中的偏见? A.微调 Fine-tuning B.数据增强 Data augmentation C.提示校准 Prompt calibration D.梯度裁剪 Gradient clipping 答案:C 提示校准包括调整提示,尽量减少产生…

干货 大模型LLM-微调经验分享总结_chatglm-6b alpaca-chinese数据集微调

导读 本文总结了作者在ChatGLM-6B模型微调的经验,并汇总了目前开源项目&数据。 写在前面 大型语言模型横行,之前非常焦虑,现在全面拥抱。目前也有很多开源项目进行大模型微调等,笔者也做了一阵子大模型了,特此来…

aspose如何获取PPT放映页“切换”的“持续时间”值

文章目录 项目场景问题描述问题1:从官方文档和资料查阅发现并没有对切换的持续时间进行处理的方法问题2:aspose的依赖包中,所有的关键对象都进行了混淆处理 解决方案1、找到ppt切换的持续时间对应的混淆对象中的字段2、获取ppt切换的持续时间…

获取vue.config.js里代理的路径

vue.config.js 主要用于配置 Vue CLI 的构建和开发服务器选项,不能直接拿到里面的值,如果是自己重新写的config,引入到页面就可以拿到 下面说,我的解决办法,如果有更好的,一定要给我说啊 在public目录下创…

设计者模式之策略模式

前言 在软件构建过程中,某些对象使用的算法可能多种多样,经常改变,如果将这些算法都写在对象中,将会使对象变得异常复杂;而且有时候支持不频繁使用的算法也是一个性能负担。 如何在运行时根据需要透明地更改对象的算…

分布式事务-SpringBoot集成Seata

1.本地事务和分布式事务概念 事务四大特性 原子性:事务不可再分一致性:数据改变前后,总量必须一致隔离性:事务之间相互隔离,互不干扰持久性:事务一旦提交,数据就会持久化到磁盘,不…

深入探讨钉钉与金蝶云星空的数据集成技术

钉钉报销数据集成到金蝶云星空的技术案例分享 在企业日常运营中,行政报销流程的高效管理至关重要。为了实现这一目标,我们采用了轻易云数据集成平台,将钉钉的行政报销数据无缝对接到金蝶云星空的付款单系统。本次案例将重点介绍如何通过API接…

【MATLAB源码-第200期】基于matlab的鸡群优化算法(CSO)机器人栅格路径规划,输出做短路径图和适应度曲线。

操作环境: MATLAB 2022a 1、算法描述 鸡群优化算法(Chicken Swarm Optimization,简称CSO)是一种启发式搜索算法,它的设计灵感来源于鸡群的社会行为。这种算法由Xian-bing Meng等人于2014年提出,旨在解决…

优阅达携手 Aiven 亮相新加坡科技周,推动企业多云数据管理与开源技术创新

助力企业在任何云上提高数据管理效率,开发个性化的创新技术解决方案。 10 月中旬, 2024 年新加坡科技周在 Marina Bay Sands 盛大举行,吸引了超过 25,000 名科技领袖、500 多家参展商和 600 多位演讲者,共同展示了全球前沿的技术…

【AIGC】国内AI工具复现GPTs效果详解

博客主页: [小ᶻZ࿆] 本文专栏: AIGC | GPTs应用实例 文章目录 💯前言💯本文所要复现的GPTs介绍💯GPTs指令作为提示词在ChatGPT实现类似效果💯国内AI工具复现GPTs效果可能出现的问题解决方法解决后的效果 &#x1…

Unreal5从入门到精通之如何在指定的显示器上运行UE程序

前言 我们有一个设备,是一个带双显示器的机柜,主显示器是一个小竖屏,可以触屏操作,大显示器是一个普通的横屏显示器。我们用这个机柜的原因就是可以摆脱鼠标和键盘,直接使用触屏操作,又可以在大屏观看,非常适合用于教学。 然后我们为这款机柜做了很多个VR项目,包括Uni…

解决linux mint22安装VMware虚拟机报错

涉及版本范围 linux内核6.8x-6.9.x vmware版本17.5.2 解决办法 wget https://github.com/nan0desu/vmware-host-modules/archive/refs/heads/tmp/workstation-17.5.2-k6.9.1.zip unzip workstation-17.5.2-k6.9.1.zip cd vmware-host-modules-tmp-workstation-17.5.2-k6.9.1…