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.rhkb.cn/news/274869.html

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

相关文章

[C语言][PTA基础C基础题目集] strtok 函数的理解与应用

一.strtok函数的解释与说明 ①strtok函数的功能 Find the next token in a string. 即查找字符串中的下一个标记. 就是将一个字符串分割成一系列的子串. ②strtok函数的原型 char *strtok( char * strToken, const char * strDelimit ); strToken: 要分割的字符串. strDel…

【机器学习】在Python中进行K-Means聚类和层次聚类

文章目录 Python中聚类算法API的使用指南K-Means 聚类步骤一&#xff1a;导入必要的库步骤二&#xff1a;加载数据步骤三&#xff1a;应用K-Means聚类步骤四&#xff1a;保存聚类结果 层次聚类步骤一&#xff1a;导入库步骤二&#xff1a;加载数据并计算距离矩阵步骤三&#xf…

MyBatis拦截器四种类型和自定义拦截器的使用流程

文章目录 MyBatis拦截器四种类型和自定义拦截器的使用流程一、MyBatis拦截器四种类型的详细解释&#xff1a;1. **ParameterHandler 拦截器**&#xff1a;2. **ResultSetHandler 拦截器**&#xff1a;3. **StatementHandler 拦截器**&#xff1a;4. **Interceptor Chain 拦截器…

Threejs粒子水波纹效果

依赖 three&#xff08;这个重要&#xff09;react &#xff08;这个不重要&#xff09;ahooks&#xff08;这个不重要&#xff09;unocss&#xff08;这个不重要&#xff09; 效果 代码 import React, { useEffect, useRef } from react; import { useGetState } from ahoo…

数据结构---C语言栈队列

知识点&#xff1a; 栈&#xff1a; 只允许在一端进行插入或删除操作的线性表&#xff0c;先进后出LIFO 类似一摞书&#xff0c;按顺序拿&#xff0c;先放的书只能最后拿&#xff1b; 顺序栈&#xff1a;栈的顺序存储 typedef struct{Elemtype data[50];int top; }SqStack; SqS…

Java实现自定义Hive认证账户密码

一、业务背景 在搭建好Hive环境后&#xff0c;应用项目远程连接hive需要设置用户名和密码&#xff0c;但hive默认的用户名和密码都是空&#xff0c;因此需要设置自定义用户名和密码。 二、开发步骤 2.1 新建maven项目&#xff0c;pom.xml引入相关依赖&#xff0c;主要是hadoop、…

RabbitMQ 面试题及答案整理,最新面试题

RabbitMQ的核心组件有哪些&#xff1f; RabbitMQ的核心组件包括&#xff1a; 1、生产者&#xff08;Producer&#xff09;&#xff1a; 生产者是发送消息到RabbitMQ的应用程序。 2、消费者&#xff08;Consumer&#xff09;&#xff1a; 消费者是接收RabbitMQ消息的应用程序…

计算机网络——计算机网络的性能

计算机网络——计算机网络的性能 速率带宽吞吐量时延时延宽带积往返时间RTT利用率信道利用率网络利用率 我们今天来看看计算机网络的性能。 速率 速率这个很简单&#xff0c;就是数据的传送速率&#xff0c;也称为数据率&#xff0c;或者比特率&#xff0c;单位为bit/s&#…

Midjourney绘图欣赏系列(七)

Midjourney介绍 Midjourney 是生成式人工智能的一个很好的例子&#xff0c;它根据文本提示创建图像。它与 Dall-E 和 Stable Diffusion 一起成为最流行的 AI 艺术创作工具之一。与竞争对手不同&#xff0c;Midjourney 是自筹资金且闭源的&#xff0c;因此确切了解其幕后内容尚不…

信息安全、网络安全以及数据安全三者之间的区别

随着信息技术的飞速发展&#xff0c;网络安全、信息安全、数据安全等词汇在平时出现的频率越来越高&#xff0c;尤其是数据安全&#xff0c;是大家都关心的一个重要话题。事实上&#xff0c;有很多人对网络安全、信息安全、数据安全的概念是区分不清的&#xff0c;下面由我帮大…

吴恩达深度学习笔记:深度学习引言1.1-1.5

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第一周&#xff1a;深度学习引言(Introduction to Deep Learning)1.1 欢迎(Welcome)1.2 什么是神经网络&#xff1f;(What is a Neural Network)1.3 神经网络的监督学习(Supervised Learning …

【PyQT/Pysider】控件背景渐变

默认渐变配色说明 background-color: qlineargradient(spread:pad, x1:0, y1:0, x2:1, y2:0, stop:0 rgba(255, 178, 102, 255), stop:0.55 rgba(235, 148, 61, 255), stop:0.98 rgba(0, 0, 0, 255), stop:1 rgba(0, 0, 0, 0));这段样式表使用了qlineargradient函数来创建…

Dynamic Wallpaper v17.4 mac版 动态视频壁纸 兼容 M1/M2

Dynamic Wallpaper Engine 是一款适用于 Mac 电脑的视频动态壁纸&#xff0c; 告别单调的静态壁纸&#xff0c;拥抱活泼的动态壁纸。内置在线视频素材库&#xff0c;一键下载应用&#xff0c;也可导入本地视频&#xff0c;同时可以将视频设置为您的电脑屏保。 应用介绍 Dynam…

chatgpt与人类有何不同?

ChatGPT和人类之间存在多个显著的差异。 首先&#xff0c;ChatGPT是一种基于人工智能技术的计算机程序&#xff0c;通过机器学习和自然语言处理等技术&#xff0c;从大量的数据中获取知识并生成语言输出。它主要依赖于算法和数据进行工作&#xff0c;能够迅速处理和检索信息&a…

Objective-C blocks 概要

1.block的使用 1.1什么是block&#xff1f; Blocks是C语言的扩充功能&#xff1a;带有自动变量&#xff08;局部变量&#xff09;的匿名函数。 “带有自动变量”在Blocks中表现为“截取自动变量" “匿名函数”就是“不带名称的函数” 块&#xff0c;封装了函数调用及调用…

制造行业大数据应用:四大领域驱动产业升级与智慧发展

一、大数据应用&#xff1a;制造行业的智慧引擎 随着大数据技术的不断突破与普及&#xff0c;制造行业正迎来一场前所未有的变革。大数据应用&#xff0c;如同智慧引擎一般&#xff0c;为制造行业注入了新的活力&#xff0c;推动了产业升级与创新发展。 二、大数据应用在制造行…

【DDR】DDR4学习记录

这里以美光DDR4芯片 MT40A512M16HA-075E datasheet 为例&#xff0c;说明DDR4存储器的原理及仿真。   根据开发板手册ug1302&#xff0c;在vcu128&#xff08;xcvu37p&#xff09;开发板上&#xff0c;共具有5块DDR4芯片&#xff0c;在数据信号上4块DDR4具有16位数据线&#…

OpenCV实战--人脸识别的三种方法(人脸识别具体到某个人)

1、前言 Opencv 中提供了三种人脸识别的方法,分别是 Eigenfaces、Fisherfaces和LBPH 三种方法都是通过对比样本特征最终实现人脸识别 因为三种算法特征提取的方式不一样,侧重点均有不同,并不能说那种方式优越,这里对三种方法进行讲解和实验 这里类似于深度学习模式,通过…

CSS 弹性盒子模型

CSS3弹性盒内容 弹性盒子由弹性容器(Flex container)和弹性子元素(Flex item)组成弹性容器通过设置display属性的值为flex将其定义为弹性容器弹性容器内包含了一个或多个弹性子元素 温馨提示&#xff1a;弹性容器外及弹性子元素内是正常渲染的。弹性盒子只定义了弹性子元素如何…

记事小本本

记事小本本 实现效果 相关代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</titl…