当前位置: 首页 > news >正文

MySQL-锁:共享锁(读)、排他锁(写)、表锁、行锁、意向锁、间隙锁,锁升级

MySQL-锁:共享锁(读)、排他锁(写)、表锁、行锁、意向锁、间隙锁

      • 共享锁(读锁)、排他锁
      • 表锁
      • 行锁
      • 意向锁
      • 间隙锁
      • 锁升级

MySQL数据库中的锁是控制并发访问的重要机制,它们确保数据的一致性和完整性。下面是MySQL数据库中常见的锁类型以及它们的特点和应用场景:

  1. 共享锁(Shared Lock)
    • 特点:共享锁允许多个事务同时读取同一资源,但阻止其他事务获取排他锁,从而防止并发写入
    • 应用场景:适用于读取操作,例如SELECT语句。
  2. 排他锁(Exclusive Lock)
    • 特点:排他锁阻塞其他事务的读锁和写锁,只允许一个事务对资源进行写操作,防止其他事务读取或写入资源
    • 应用场景:适用于写入或修改操作,例如INSERTUPDATEDELETE语句。
  3. 表锁(Table Lock)
    • 特点:表锁会锁定整张表阻塞其他事务对表的写操作,但不阻塞对表的读操作
    • 应用场景:适用于对整张表进行操作的场景,例如MyISAM存储引擎的表级锁
  4. 行锁(Row Lock)
    • 特点:行锁允许事务锁定表中的特定行,而不是整张表,提高并发性。但容易引发死锁
    • 应用场景:适用于需要精确控制行级别访问的场景,例如InnoDB存储引擎的行级锁
  5. 意向锁(Intention Locks)
    • 意向锁是一种表明事务将在某个级别上加锁的锁类型。意向锁有两种类型:意向共享锁意向排他锁。它们用于表示一个事务打算在一个更高的层级上(如行级别或表级别)加锁
    • 意向锁是为了帮助数据库管理系统了解一个事务打算在哪个级别上进行锁定,以便避免死锁
  6. 间隙锁(Gap Locks)
    • 间隙锁是一种特殊类型的锁,用于防止其他事务将新的键插入到已有的索引范围中。间隙锁在某个范围的键之间创建了一个间隙防止其他事务插入新的键
    • 间隙锁通常与范围查询操作一起使用,例如SELECT ... WHERE ... BETWEEN ... AND ...语句。

现在,让我们来看一个实际案例,说明MySQL中锁的应用

假设有一个电子商务网站,多个用户同时访问产品库存信息,并尝试下单购买同一件商品,这时候可能会涉及到对产品库存的读写操作。

  • 对于读取产品库存信息的操作,可以使用共享锁(读锁)允许多个用户同时读取产品库存信息,不会互相阻塞,保证并发性
  • 当某个用户下单购买商品时,需要更新产品库存信息,此时需要使用排他锁(写锁),阻止其他用户同时修改库存信息,确保数据的一致性

如果没有使用合适的锁机制,可能会导致以下问题

  • 如果多个用户同时读取产品库存信息但不加锁,则可能读取到错误的库存数量
  • 如果多个用户同时尝试购买同一件商品而没有加锁,则可能导致超卖或者库存错误的问题

共享锁(读锁)、排他锁

CREATE TABLE articles (article_id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255),content TEXT
);

事务1:查看博客文章内容(共享锁)

共享锁允许多个事务同时读取同一资源,但阻止其他事务获取排他锁,从而防止并发写入

START TRANSACTION;
SELECT * FROM articles WHERE article_id = 123 LOCK IN SHARE MODE;
-- 读取文章内容
COMMIT;

事务2:可以编辑文章内容(排他锁)

排他锁阻塞其他事务的读锁和写锁,只允许一个事务对资源进行写操作,防止其他事务读取或写入资源

START TRANSACTION;
SELECT * FROM articles WHERE article_id = 123 FOR UPDATE;
-- 编辑文章内容
UPDATE articles SET content = 'New content' WHERE article_id = 123;
COMMIT;

在这里插入图片描述

表锁

假设有一个在线预订系统,有一个订单表,需要定期对订单表进行清理和维护操作

CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMARY KEY,customer_id INT,order_date DATETIME
);
-- 事务1:清理过期订单(表锁)
START TRANSACTION;
LOCK TABLES orders WRITE;
-- 清理过期订单
DELETE FROM orders WHERE order_date < DATE_SUB(NOW(), INTERVAL 30 DAY);
UNLOCK TABLES;
COMMIT;

在这里插入图片描述

在这里插入图片描述

行锁

假设有一个在线论坛系统,用户可以对帖子进行评论,需要确保在用户对同一篇帖子进行评论时不会产生冲突。

CREATE TABLE posts (post_id INT AUTO_INCREMENT PRIMARY KEY,title VARCHAR(255),content TEXT
);CREATE TABLE comments (comment_id INT AUTO_INCREMENT PRIMARY KEY,post_id INT,user_id INT,comment_text TEXT,
);
-- 事务1:添加评论(行锁)
START TRANSACTION;
SELECT * FROM posts WHERE post_id = 123 FOR UPDATE;
-- 添加评论
INSERT INTO comments (post_id, user_id, comment_text) VALUES (123, 456, 'Great post!');
COMMIT;

事务执行SELECT * FROM posts WHERE post_id = 123 FOR UPDATE;语句获取了帖子ID为123的行级排他锁。这样做的目的是确保在添加评论之前,对于帖子ID为123的行数据,其他事务无法同时修改,以避免数据不一致或丢失的情况发生

意向锁

假设有一个在线购物系统,其中有两张表:orders(订单表)和order_details(订单详情表)。订单表记录了每个订单的基本信息,订单详情表则记录了每个订单中的具体商品信息。

CREATE TABLE orders (id INT AUTO_INCREMENT PRIMARY KEY,customer_id INT,order_date DATETIME
);CREATE TABLE order_details (id INT AUTO_INCREMENT PRIMARY KEY,order_id INT,product_id INT,quantity INT,
);

现在假设有一个事务需要向订单表中插入一条新的订单记录,并且需要向订单详情表中插入相关的商品信息。

START TRANSACTION;-- 获取意向排他锁,表明将在订单表上进行排他锁定
SELECT * FROM orders WHERE customer_id = 100 FOR UPDATE;-- 插入新的订单记录
INSERT INTO orders (customer_id, order_date) VALUES (100, NOW());
SET @last_order_id = LAST_INSERT_ID();-- 插入订单详情
INSERT INTO order_details (order_id, product_id, quantity) VALUES (@last_order_id, 1, 2);
INSERT INTO order_details (order_id, product_id, quantity) VALUES (@last_order_id, 2, 3);COMMIT;

初始:

在这里插入图片描述

执行事务后:

在这里插入图片描述

在这个例子中,事务首先获取了意向排他锁,以表明将在订单表上进行排他锁定。然后向订单表中插入了一条新的订单记录,并且通过获取LAST_INSERT_ID()函数获取了刚插入的订单ID,接着向订单详情表中插入了相关的商品信息。

间隙锁

假设有一个产品表,其中的产品ID是一个唯一索引。现在有两个事务,一个事务需要检查某个特定的产品是否存在,而另一个事务需要向产品表中插入一个新的产品。

-- 事务1:检查产品是否存在
START TRANSACTION;
SELECT * FROM products WHERE product_id = 5 LOCK IN SHARE MODE;
-- 如果存在特定产品,则执行相应操作
COMMIT;-- 事务2:插入新的产品
START TRANSACTION;
-- 获取间隙锁,防止其他事务在该范围内插入新的产品
SELECT * FROM products WHERE product_id > 4 AND product_id < 6 FOR UPDATE;
-- 插入新的产品
INSERT INTO products (product_id, name, price) VALUES (5, 'New Product', 10.99);
COMMIT;

事务1:检查产品是否存在

在这里插入图片描述

START TRANSACTION;
SELECT * FROM products WHERE product_id = 5 LOCK IN SHARE MODE;
-- 如果存在特定产品,则执行相应操作
INSERT INTO products (product_id, name, price) VALUES (5, 'New Product', 23.11);
COMMIT;

无法插入

在这里插入图片描述

在这个事务中,我们使用LOCK IN SHARE MODE语句获取了产品ID为5的共享锁,以确保其他事务可以同时读取相同的产品信息,但是不能进行写操作。

事务2:插入新的产品

在这里插入图片描述

START TRANSACTION;
-- 获取间隙锁,防止其他事务在该范围内插入新的产品
SELECT * FROM products WHERE product_id > 4 AND product_id < 6 FOR UPDATE;
-- 插入新的产品
INSERT INTO products (product_id, name, price) VALUES (5, 'New Product', 10.99);
COMMIT;

无法插入

在这里插入图片描述

在这个事务中,我们使用FOR UPDATE语句获取了产品ID大于4且小于6的间隙锁,以防止其他事务在这个范围内插入新的产品。然后,我们向产品表中插入了一个新的产品。

锁升级

在MySQL中,锁升级是指事务在执行过程中,将当前持有的锁从低级别升级到更高级别的过程。这个过程通常是为了保证数据的完整性和一致性,同时尽量减少锁的持有时间,以提高并发性能。

MySQL中的锁升级有时是隐式的,有时需要显式操作。以下是一些锁升级的例子,以及相应的SQL语句:

CREATE TABLE products (id INT AUTO_INCREMENT PRIMARY KEY,name VARCHAR(255),category_id INT,price DECIMAL(10, 2),quantity INT
);CREATE TABLE orders (id INT AUTO_INCREMENT PRIMARY KEY,customer_id INT,product_id INT,quantity INT,order_date DATETIME,
);
  1. 从行级锁升级到表级锁

    例子:

    START TRANSACTION;
    SELECT * FROM products WHERE category_id = 1 FOR UPDATE;
    -- 此时事务持有了行级锁-- 执行一些操作,需要将行级锁升级到表级锁
    UPDATE products SET price = price * 0.9 WHERE category_id = 1;COMMIT;
    

    在这个例子中,事务开始时使用SELECT ... FOR UPDATE语句获取了category_id为1的产品行的排他锁,随后执行更新操作需要将行级锁升级为表级锁。

  2. 从共享锁升级到排他锁

    例子:

    START TRANSACTION;
    SELECT * FROM products WHERE category_id = 1 LOCK IN SHARE MODE;
    -- 此时事务持有了共享锁-- 执行一些操作,需要将共享锁升级到排他锁
    UPDATE products SET quantity = quantity - 1 WHERE category_id = 1;COMMIT;
    

    在这个例子中,事务开始时使用LOCK IN SHARE MODE语句获取了category_id为1的产品行的共享锁,但在后续执行中需要对该行进行修改,因此需要将共享锁升级为排他锁。

  3. 从意向锁升级到表级锁

    例子:

    START TRANSACTION;
    SELECT * FROM orders WHERE customer_id = 100 FOR UPDATE;
    -- 此时事务持有了意向排他锁-- 执行一些操作,需要将意向锁升级为表级锁
    DELETE FROM orders WHERE customer_id = 100;COMMIT;
    

    在这个例子中,事务开始时使用SELECT ... FOR UPDATE语句获取了customer_id为100的订单行的意向排他锁,后续执行了删除操作,需要将意向锁升级为表级锁。

相关文章:

MySQL-锁:共享锁(读)、排他锁(写)、表锁、行锁、意向锁、间隙锁,锁升级

MySQL-锁&#xff1a;共享锁&#xff08;读&#xff09;、排他锁&#xff08;写&#xff09;、表锁、行锁、意向锁、间隙锁 共享锁&#xff08;读锁&#xff09;、排他锁表锁行锁意向锁间隙锁锁升级 MySQL数据库中的锁是控制并发访问的重要机制&#xff0c;它们确保数据的一致性…...

docker 使用官方镜像搭建 PHP 环境

一、所需环境&#xff1a; 1、PHP&#xff1a;7.4.33-fpm 的版本 2、Nginx&#xff1a;1.25.1 的版本 3、MySQL&#xff1a; 5.7 的版本 4、Redis&#xff1a;7.0 的版本 1.1、拉取官方的镜像 docker pull php:7.4.33-fpm docker pull nginx:1.25.1 docker pull mysql:5.7 do…...

STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置

STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件偏好设置前言第1章 设置字体颜色第2章 设置字体大小第3章 设置代码区背景颜色总结 前言 编程软件环境最好就设置一个自己喜欢的界面进行显示&#xff0c;这样看起来会比较舒服些…...

【《高性能 MySQL》笔记】性能优化

学习知识最快最好的方式就是问对问题。 本文将通过“问正确的问题”的方式循序渐进地深入总结性能优化相关知识。 性能优化基础 Q1:什么是“性能”? 即响应时间(RT,Response Time),完成某个任务所需要的时间度量。 Q2:什么是“性能优化”? 性能优化为在一定工作负…...

Spring AOP底层原理

目录 代理模式 静态代理 动态代理 1. JDK动态代理 创建⼀个代理对象并使用 2. CGLIB动态代理 SpringAOP底层原理面试 代理模式 Spring AOP是基于动态代理模式来实现的 代理模式&#xff1a;静态代理模式动态代理模式 代理模式, 也叫委托模式。 定义&#xff1a;为其…...

proteus8.9 示波器放大

proteus8.9 示波器放大** 1. 打开放大&#xff1a;Windows徽标键 加号 2. 取消放大&#xff1a;Windows徽标键 ESC...

代码随想录训练营第41天 | 动态规划:01背包理论基础、动态规划:01背包理论基础(滚动数组)、LeetCode 416.分割等和子集

动态规划&#xff1a;01背包理论基础 文章讲解&#xff1a;代码随想录(programmercarl.com) 视频讲解&#xff1a;带你学透0-1背包问题&#xff01;_哔哩哔哩_bilibili 动态规划&#xff1a;01背包理论基础&#xff08;滚动数组&#xff09; 文章讲解&#xff1a;代码随想录(…...

1908_Arm Cortex-M3的实现

1908_Arm Cortex-M3的实现 全部学习汇总&#xff1a; g_arm_cores: ARM内核的学习笔记 (gitee.com) 这是第一次看一份这样的手册&#xff0c;之前的MCU编程基本上就是专注于软件接口方面。而OS等方面的一些功能基本上都是用了现成的解决方案&#xff0c;因此也就没有过多的关注…...

编程笔记 html5cssjs 005 小学数学四则运算练习

编程笔记 html5&css&js 005 小学数学四则运算练习 一、代码二、解释 这段代码定义了一个页面&#xff0c;用于小学数学四则运算的练习。这可能有点难&#xff0c;实际如果需要可以通过更改代码来达到要求。 一、代码 <!DOCTYPE html> <html lang"zh&quo…...

【大厂AI课学习笔记NO.71】AI算力芯片GPU/TPU等

AI算力芯片的发展历程 人工智能&#xff08;AI&#xff09;算力芯片的发展历程紧密地跟随着AI技术的发展脚步。从早期的基于传统中央处理器&#xff08;CPU&#xff09;的计算&#xff0c;到图形处理器&#xff08;GPU&#xff09;的广泛应用&#xff0c;再到专门为AI设计的处…...

浅谈Redis和分布式系统

浅谈Redis Redis用于存储数据&#xff0c;且在内存当中进行存储。 但是在日常编写代码中&#xff0c;定义一个变量也就属于在内存当中存储一个数据。 Redis主要会在分布式系统当中发挥重要作用&#xff0c;如果只是单机程序&#xff0c;直接通过变量存储数据的方式会比使用Re…...

微信小程序onLoad加载定义好的函数

这里小程序开发中容易犯的错误-1 给客户做一个程序。需要在页面加载的时候在onLoad(options){}中加载定义好的函数&#xff0c;代码如下 onLoad(options) {get_week_()},运行时老报错 后来修改为正确的代码 onLoad(options) {this.get_week_()//必须加this},再尝试运行&#x…...

C++进阶:详细讲解继承

现在也是结束了初阶部分的内容&#xff0c;今天开始就进入进阶部分了。一刻也没有为初阶的结束而哀悼&#xff0c;立刻赶来“战场”的是进阶部分里的继承 文章目录 1.继承的概念和定义1.1继承的概念1.2继承的定义1.2.1继承的格式1.2.2再讲访问限定符(详讲protected)1.2.3**继承…...

第十一篇 - 应用于市场营销视频场景中的人工智能和机器学习技术 – Video --- 我为什么要翻译介绍美国人工智能科技巨头IAB公司(1)

IAB平台&#xff0c;使命和功能 IAB成立于1996年&#xff0c;总部位于纽约市。 作为美国的人工智能科技巨头社会媒体和营销专业平台公司&#xff0c;互动广告局&#xff08;IAB- the Interactive Advertising Bureau&#xff09;自1996年成立以来&#xff0c;先后为700多家媒体…...

基于决策树实现葡萄酒分类

基于决策树实现葡萄酒分类 将葡萄酒数据集拆分成训练集和测试集&#xff0c;搭建tree_1和tree_2两个决策树模型&#xff0c;tree_1使用信息增益作为特征选择指标&#xff0c;B树使用基尼指数作为特征选择指标&#xff0c;各自对训练集进行训练&#xff0c;然后分别对训练集和测…...

上位机图像处理和嵌入式模块部署(qmacvisual三个特色)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 了解了qmacvisual的配置之后&#xff0c;正常来说&#xff0c;我们需要了解下不同插件的功能是什么。不过我们不用着急&#xff0c;可以继续学习下…...

电脑解锁后黑屏有鼠标--亲测!!不需要重装系统!!

问题&#xff1a;上周电脑黑屏&#xff0c;只有鼠标&#xff0c;鼠标还不能右键&#xff01;&#xff01; 中招&#xff1a;win10系统最新版火绒安全 &#xff0c;那你有概率获得开机黑屏套餐一份。 原因是&#xff1a;火绒把我们的explorer删除了导致黑屏&#xff0c;这个文…...

Spring 事务的种类 ? 传播机制 ?

在Spring框架中&#xff0c;事务管理可以分为编程式事务和声明式事务两种主要形式。每种形式都有其特点和使用场景。以下是这两种形式的具体介绍&#xff1a; 编程式事务 编程式事务是通过编写代码来实现事务管理的。在Spring中&#xff0c;编程式事务管理通常通过Transactio…...

深入了解 Java 方法和参数的使用方法

Java 方法 简介 方法是一块仅在调用时运行的代码。您可以将数据&#xff08;称为参数&#xff09;传递到方法中。方法用于执行特定的操作&#xff0c;它们也被称为函数。 使用方法的原因 重用代码&#xff1a;定义一次代码&#xff0c;多次使用。提高代码的结构化和可读性。…...

自动驾驶技术解析与关键步骤

目录 前言1 自动驾驶主要技术流程1.1 车辆周围环境感知1.2 车辆和行人检测分析1.3 运动轨迹规划 2 关键技术概述2.1 车辆探测与图片输入2.2 行人检测2.3 运动规划2.4 电子地图2.5 轨迹预测2.6 交通灯分析2.7 故障检测 结语 前言 自动驾驶汽车作为未来交通领域的重要发展方向&a…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

XCTF-web-easyupload

试了试php&#xff0c;php7&#xff0c;pht&#xff0c;phtml等&#xff0c;都没有用 尝试.user.ini 抓包修改将.user.ini修改为jpg图片 在上传一个123.jpg 用蚁剑连接&#xff0c;得到flag...

内存分配函数malloc kmalloc vmalloc

内存分配函数malloc kmalloc vmalloc malloc实现步骤: 1)请求大小调整:首先,malloc 需要调整用户请求的大小,以适应内部数据结构(例如,可能需要存储额外的元数据)。通常,这包括对齐调整,确保分配的内存地址满足特定硬件要求(如对齐到8字节或16字节边界)。 2)空闲…...

【Oracle APEX开发小技巧12】

有如下需求&#xff1a; 有一个问题反馈页面&#xff0c;要实现在apex页面展示能直观看到反馈时间超过7天未处理的数据&#xff0c;方便管理员及时处理反馈。 我的方法&#xff1a;直接将逻辑写在SQL中&#xff0c;这样可以直接在页面展示 完整代码&#xff1a; SELECTSF.FE…...

【JavaEE】-- HTTP

1. HTTP是什么&#xff1f; HTTP&#xff08;全称为"超文本传输协议"&#xff09;是一种应用非常广泛的应用层协议&#xff0c;HTTP是基于TCP协议的一种应用层协议。 应用层协议&#xff1a;是计算机网络协议栈中最高层的协议&#xff0c;它定义了运行在不同主机上…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具&#xff0c;该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具&#xff0c;其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利&#xff0c;如安装和调试…...

PHP和Node.js哪个更爽?

先说结论&#xff0c;rust完胜。 php&#xff1a;laravel&#xff0c;swoole&#xff0c;webman&#xff0c;最开始在苏宁的时候写了几年php&#xff0c;当时觉得php真的是世界上最好的语言&#xff0c;因为当初活在舒适圈里&#xff0c;不愿意跳出来&#xff0c;就好比当初活在…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

基础测试工具使用经验

背景 vtune&#xff0c;perf, nsight system等基础测试工具&#xff0c;都是用过的&#xff0c;但是没有记录&#xff0c;都逐渐忘了。所以写这篇博客总结记录一下&#xff0c;只要以后发现新的用法&#xff0c;就记得来编辑补充一下 perf 比较基础的用法&#xff1a; 先改这…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...