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的订单行的意向排他锁,后续执行了删除操作,需要将意向锁升级为表级锁。

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

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

相关文章

SQL中常见的DDL操作及示例,数据库操作及表操作

目录 一、数据库操作 1、创建数据库 2、查看所有数据库 3、使用数据库 4、删除数据库 二、表操作&#xff1a; 1、创建表 2、查看表结构 3、修改表结构 3.1 添加列 3.2 修改列数据类型 3.3 修改列名 3.4 删除列 3.5 修改表名 3.6 删除表 注意&#xff1a; 在数…

数字化解决方案的设计与实现:提升业务效率与用户体验

摘要&#xff1a;随着数字化时代的到来&#xff0c;越来越多的企业和组织开始寻求数字化解决方案来提升业务效率和改善用户体验。本文将探讨数字化解决方案的设计与实现过程&#xff0c;并介绍一些关键的技术和策略。 ## 引言 在当今竞争激烈的商业环境中&#xff0c;企业和组…

Unity 轮转图, 惯性, 自动回正, 点击选择

简单的实现 2D 以及 3D 的轮转图, 类似于 Web 中无限循环的轮播图那样. 文中所有代码均已同步至 github.com/SlimeNull/UnityTests 3D 轮转图: Assets/Scripts/Scenes/CarouselTestScene/Carousel.cs2D 轮转图: Assets/Scripts/Scenes/CarouselTestScene/UICarousel.cs 主要逻…

HashMap的底层实现

1、1.7版本的底层实现 HashMap在1.7版本中数据结构是数组链表&#xff0c; 1.1 put方法 put方法中操作步骤&#xff1a; &#xff08;1&#xff09;、对key计算相应的hash值&#xff0c;然后通过hash & table.length-1计算可以获得到在hash表中中相应的桶位置&#xff…

海外媒体宣发套餐如何利用3种方式洞察市场-华媒舍

在当今数字化时代&#xff0c;媒体宣发成为了企业推广产品和品牌的重要手段之一。其中&#xff0c;7FT媒体宣发套餐是一种常用而有效的宣传方式。本文将介绍这种媒体宣发套餐&#xff0c;以及如何利用它来洞察市场。 一、关键概念 在深入讨论7FT媒体宣发套餐之前&#xff0c;让…

golang实现正向代理和反向代理

文章目录 正向代理反向代理区别与联系:总结代理服务器实现正向代理反向代理正向代理 正向代理是客户端代理,它位于客户端和目标服务器之间。它的作用是保护客户端的隐私和安全。 如我们现在想要访问谷歌,但是由于某些原因,无法直接访问到谷歌,我们可以通过连接一台代理服务…

STM32_3-1点亮LED灯与蜂鸣器发声

STM32之GPIO GPIO在输出模式时可以控制端口输出高低电平&#xff0c;用以驱动Led蜂鸣器等外设&#xff0c;以及模拟通信协议输出时序等。 输入模式时可以读取端口的高低电平或电压&#xff0c;用于读取按键输入&#xff0c;外接模块电平信号输入&#xff0c;ADC电压采集灯 GP…

【NERF】入门学习整理(二)

【NERF】入门学习整理(二) 1. Hierarchicalsampling分层采样2. Loss定义(其实就是简单的均方差MSE)3. 隐式重建与显示重建1. Hierarchicalsampling分层采样 粗网络coarse,均匀采样64个点 缺点:如果仅使用粗网络会存在点位浪费和欠采样的问题,比比如空气中很多无效的点 精细…

【C语言】文件操作篇-----程序文件和数据文件,文件的打开和关闭,二进制文件和文本文件,fopen,fclose【图文详解】

欢迎来CILMY23的博客喔&#xff0c;本篇为【C语言】文件操作篇-----程序文件和数据文件&#xff0c;文件的打开和关闭&#xff0c;二进制文件和文本文件【图文详解】&#xff0c;感谢观看&#xff0c;支持的可以给个一键三连&#xff0c;点赞关注收藏。 前言 在了解完动态内存管…

运维随录实战(13)之docker搭建mysql集群(pxc)

了解 MySQL 集群之前,先看看单节点数据库的弊病 大型互联网程序用户群体庞大,所以架构需要特殊设计。单节点数据库无法满足大并发时性能上的要求。单节点的数据库没有冗余设计,无法满足高可用。单节点 MySQL无法承载巨大的业务量,数据库负载巨大常见 MySQL 集群方案 Re…

少儿编程 蓝桥杯青少组科技素养题 信息素养真题及解析第25套

少儿编程 科技素养 信息素养真题第25套 1、旅行结束之后&#xff0c;回到家的小蓝决定将照片备份在云端的网盘上。备份照片主要占用的是小蓝家的( )带宽 A、下行 B、上行 C、文件 D、数据 答案&#xff1a;B 考点分析&#xff1a;主要考查网络相关知识&#xff0c;要将照…

DHCP中继实验(华为)

思科设备参考&#xff1a; 一&#xff0c;技术简介 DHCP中继&#xff0c;可以实现在不同子网和物理网段之间处理和转发DHCP信息的功能。如果DHCP客户机与DHCP服务器在同一个物理网段&#xff0c;则客户机可以正确地获得动态分配的IP地址。如果不在同一个物理网段&#xff0c;…

JVM知识整体学习

前言&#xff1a;本篇没有任何建设性的想法&#xff0c;只是我很早之前在学JVM时记录的笔记&#xff0c;只是想从个人网站迁移过来。文章其实就是对《深入理解JVM虚拟机》的提炼&#xff0c;纯基础知识&#xff0c;网上一搜一大堆。 一、知识点脑图 本文只谈论HotSpots虚拟机。…

C# 视频转图片

在 C# 中将视频转换为图像可以使用 FFmpeg 库。下面是一个示例代码来完成这个任务&#xff1a; using System; using System.Diagnostics;class Program {static void Main(string[] args){string inputFile "input_video.mp4"; // 输入的视频文件路径string outpu…

【Leetcode打卡】递归回溯

【Leetcode打卡】递归回溯 784. 字母大小写全排列 class Solution { public:int find(string s,int pos){int ipos;while(i<s.size()){if(isalpha(s[i])){return i;}i;}return -1;}void turn(string& s,int pos){if(islower(s[pos])){s[pos]toupper(s[pos]);}else{s[po…

思科网络中如何配置标准ACL协议

一、什么是标准ACL协议&#xff1f;有什么作用及配置方法&#xff1f; &#xff08;1&#xff09;标准ACL&#xff08;Access Control List&#xff09;协议是一种用于控制网络设备上数据流进出的协议。标准ACL基于源IP地址来过滤数据流&#xff0c;可以允许或拒绝特定IP地址范…

离散数学例题——7.代数系统和群论

代数系统定义 二元运算律 特殊元素 逆元 子代数系统 同态同构 半群和独异点&#xff08;含幺半群&#xff09; 群和阿贝尔群 常见群和群的证明 群的性质 群的幂 群元素的阶 群的同态同构 子群 子群证明

修改简化docker命令

修改|简化docker命令 使用命令打开 .bashrc 文件&#xff1a; vim ~/.bashrc在文件中添加类似以下行来创建别名&#xff1a; # 查看所有容器 alias disdocker images # 查看运行容器 alias dpsdocker ps # 查看所有容器 alias dpsadocker ps -a # 停止容器 alias dsdocker s…

【Claude 3】一文谈谈Anthropic(Claude) 亚马逊云科技(Bedrock)的因缘际会

文章目录 前言1. Anthropic的诞生2. Anthropic的“代表作”——Claude 3的“三驾马车”3. 亚马逊云科技介绍4. 强大的全托管服务平台——Amazon Bedrock5. 亚马逊云科技(AWS)和Anthropic的联系6. Claude 3模型与Bedrock托管平台的关系7. Clude 3限时体验入口分享【⚠️截止3月1…

flask-sqlalchemy库

彩笔激流勇退。 1. 简介 ORM&#xff0c;对象关系映射。简单来说&#xff0c;ORM将数据库中的表与面向对象中的类建立了一种对应关系。这样&#xff0c;我们要操作数据库&#xff0c;表&#xff0c;记录就可以直接通过操作类或者类实例来完成。 SQLAlchemy 是目前python中最…