MySQL锁的概念

  1. 锁的基本概念

    • 锁在 MySQL 中是一种并发控制机制,它确保在多用户或多事务环境下数据的完整性和一致性。当多个事务同时访问和操作数据库中的数据时,为了防止数据出现不一致、丢失更新、脏读、不可重复读和幻读等问题,就需要使用锁来协调这些事务的访问顺序。例如,在一个银行转账系统中,如果没有锁机制,两个事务同时对同一个账户进行操作,就可能导致数据错误。
  2. 锁的类型

    • 共享锁(S Lock,也叫读锁)
      • 共享锁允许同时有多个事务对同一数据进行读取操作。一个事务对数据加上共享锁后,其他事务可以继续对该数据加共享锁来读取,但不能加排他锁进行写操作。这是因为共享锁的目的是实现多个事务对数据的并发读取。例如,在一个图书馆的图书信息管理系统中,多个用户可以同时查询某一本书的信息,此时对图书信息表中的记录加共享锁,就可以满足这种并发读取的需求。
      • 共享锁的语法在不同的存储引擎和操作方式下有所不同。在 InnoDB 存储引擎中,使用SELECT... LOCK IN SHARE MODE语句来对查询的数据加共享锁。例如:SELECT * FROM books WHERE book_id = 1 LOCK IN SHARE MODE;,这表示在查询图书编号为 1 的图书信息时,对该记录加共享锁,其他事务可以同时对这条记录加共享锁进行读取,但不能进行写操作。
    • 排他锁(X Lock,也叫写锁)
      • 排他锁用于对数据进行写操作,如插入、更新和删除操作。当一个事务对数据加上排他锁后,其他事务不能对该数据加任何类型的锁,无论是共享锁还是排他锁,直到该事务释放排他锁。这是因为写操作通常需要对数据进行独占式的访问,以确保数据的准确性。例如,在一个库存管理系统中,当一个事务正在更新某一商品的库存数量时,对该商品的库存记录加排他锁,其他事务就不能同时对这条记录进行读取或写入操作,直到库存更新事务完成。
      • 在 InnoDB 存储引擎中,FOR UPDATE语句用于对查询的数据加排他锁。例如:SELECT * FROM inventory WHERE product_id = 1 FOR UPDATE;,这表示在查询商品编号为 1 的库存信息时,对该记录加排他锁,其他事务在这个锁释放之前不能对这条记录进行任何操作。
  3. 锁的粒度

    • 表锁
      • 表锁是对整个表进行锁定。它的实现相对简单,管理锁的开销较小,因为只需要维护一个表级别的锁状态。当一个事务对表加表锁后,其他事务对该表的任何操作(包括读取和写入)都需要等待锁的释放。这种方式在一些简单的场景下比较适用,例如对整个表进行批量更新或者备份操作时。
      • 在 MySQL 中,可以使用LOCK TABLES语句来手动加表锁。例如:LOCK TABLES orders WRITE;,这是对orders表加排他表锁(WRITE表示排他锁),用于对该表进行写操作。如果要加共享表锁,可以使用READ关键字,如LOCK TABLES customers READ;,这表示对customers表加共享表锁,用于对该表进行读操作。需要注意的是,在使用LOCK TABLES语句后,一定要记得使用UNLOCK TABLES语句来释放锁。
    • 行锁
      • 行锁是对表中的行进行锁定。它提供了更高的并发性能,因为不同的事务可以对同一表中的不同行进行加锁操作。这样可以允许多个事务同时对一张表进行读写操作,只要它们操作的是不同的行。不过,行锁的管理开销较大,因为需要为每一行维护锁状态。
      • InnoDB 存储引擎默认支持行锁。它是通过索引来实现行锁的,如果在操作过程中没有合适的索引,可能会导致行锁升级为表锁。例如,在一个用户表中,有主键索引(假设是user_id),当一个事务执行SELECT * FROM users WHERE user_id = 1 FOR UPDATE;时,InnoDB 会对user_id为 1 的行记录加行锁。这样其他事务可以对其他用户记录进行操作,而不会受到这个事务的影响。
    • 页锁(介于表锁和行锁之间)
      • 页锁是对存储引擎中的页(一般为固定大小的数据块,如 InnoDB 的页大小通常为 16KB)进行加锁。页锁的并发性能和管理开销介于表锁和行锁之间。它的使用相对较少,主要是因为在实际应用中,要么需要对整个表进行操作(适合用表锁),要么需要对具体的行进行操作(适合用行锁)。不过,在某些特定的场景下,页锁可能会发挥作用,例如在对一个数据页内的多个相关行进行批量操作时,页锁可以提供一定的性能优势。
  4. InnoDB 中的锁机制

    • 意向锁
      • 意向锁是 InnoDB 存储引擎自动添加的一种锁,用于表示事务在更高层次(表层次)上的锁意向。它分为意向共享锁(IS)和意向排他锁(IX)。当事务对表中的行加共享锁时,会自动对表加意向共享锁;当事务对表中的行加排他锁时,会自动对表加意向排他锁。
      • 意向锁的存在主要是为了方便事务在操作行锁时,能够快速判断表是否被其他事务锁定。例如,在一个复杂的多事务环境中,当一个事务想要对一个表中的行加锁时,通过检查表上是否有意向锁,可以快速确定是否有其他事务正在对该表中的行进行操作。如果表上有意向排他锁,那么新的事务就知道不能对表中的行随意加锁,需要等待锁的释放。
    • 记录锁(行锁)
      • 记录锁是对单个行记录进行锁定。在使用索引进行查询并更新数据时,InnoDB 通常会对满足条件的行记录加记录锁。例如,在一个有主键索引的表中,通过主键查询并修改一行数据时,会对该行加记录锁。记录锁的作用是确保在一个事务对某一行进行操作时,其他事务不能对同一行进行冲突操作。
      • 假设在一个员工信息表employees中有主键employee_id,当一个事务执行UPDATE employees SET salary = 5000 WHERE employee_id = 101;时,InnoDB 会对employee_id为 101 的行加记录锁,这样其他事务就不能同时修改这一行的工资信息。
    • 间隙锁(Gap Lock)
      • 间隙锁用于锁定一个范围,但不包括记录本身。它主要用于防止幻读现象,在可重复读(Repeatable Read)隔离级别下发挥重要作用。幻读是指一个事务在两次查询同一范围的数据时,第二次查询出现了第一次查询没有出现的新数据。
      • 例如,在一个成绩表scores中,有一个分数范围查询SELECT * FROM scores WHERE score BETWEEN 80 AND 90;,在可重复读隔离级别下,InnoDB 可能会对分数在 80 到 90 之间的间隙(不包括 80 和 90 这两个端点对应的记录,如果它们存在的话)加间隙锁。这样,当这个事务在操作过程中,其他事务就不能在这个间隙中插入新的记录,从而避免了幻读现象。
    • 临键锁(Next - Key Lock)
      • 临键锁是记录锁和间隙锁的组合。它既锁定一个记录,又锁定该记录前面的间隙。临键锁的范围是前开后闭区间,它在索引遍历过程中,用于防止其他事务在该区间插入新的数据,从而保证数据的一致性和隔离性。
      • 例如,在一个按照年龄排序的人员表persons中,索引是age。当一个事务执行SELECT * FROM persons WHERE age >= 30 AND age < 40;时,InnoDB 会对age大于等于 30 且小于 40 的记录以及这些记录前面的间隙加临键锁。这意味着其他事务不能在这个区间插入新的记录,同时也不能修改这个区间内已有的记录,确保了这个事务在这个区间内读取数据的一致性。
  5. 锁的使用场景和优化

    • 高并发读取场景
      • 在以读为主的高并发场景下,如新闻网站的文章查询、搜索引擎的索引数据查询等,共享锁是非常有用的。可以通过合理的索引设计,使得多个事务能够快速定位到需要读取的数据,并且加共享锁进行并发读取。例如,对于新闻文章表,可以根据文章类别、发布时间等建立索引,方便查询操作。
      • 同时,为了避免过多的锁竞争,可以采用一些缓存策略,如将经常访问的文章内容缓存到内存中,减少对数据库的直接查询和锁的使用。另外,还可以根据业务需求适当调整事务的隔离级别,在保证数据一致性的前提下,提高并发读取的性能。
    • 高并发写入场景
      • 在高并发写入场景下,如电商系统的订单处理、社交平台的用户信息更新等,充分利用行锁的优势至关重要。通过合理的数据库架构和索引设计,确保每个事务能够准确地对需要操作的行加行锁,避免不必要的表锁。例如,在电商订单表中,以订单编号作为主键,当处理不同订单时,通过主键索引对不同订单记录加行锁,实现高并发的订单处理。
      • 此外,可以采用乐观锁机制来替代部分排他锁的使用,提高并发性能。例如,在库存管理系统中,为每个库存记录添加一个版本号字段。当更新库存时,先查询出库存记录和对应的版本号,然后在更新时判断版本号是否一致,如果一致则更新库存并递增版本号,否则说明有其他事务已经更新了库存,需要重新查询和更新。
    • 长事务和锁等待
      • 长事务可能会导致锁长时间占用,从而影响其他事务的执行。为了尽量缩短事务的执行时间,避免长时间的锁等待,可以对 SQL 语句进行优化。例如,减少不必要的查询和更新操作,将复杂的事务拆分成多个小事务,提高事务的执行效率。
      • 同时,对业务逻辑进行合理设计,避免在事务中进行耗时的操作,如网络请求、文件读写等。另外,监控数据库的锁等待情况,及时发现和解决长时间的锁等待问题,也是优化数据库性能的重要环节。可以通过数据库的性能监控工具来查看锁等待的统计信息,如锁等待的次数、等待时间等,根据这些信息来调整数据库的配置和应用程序的逻辑。

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

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

相关文章

Java-多种方法实现多线程卖票

Java多线程卖票是一个经典的并发编程问题,它展示了如何在多个线程之间安全地共享和修改资 源。以下是几种实现方式: 使用synchronized关键字: 使用synchronized修饰符来同步方法或代码块,确保同一时刻只有一个线程可以访问临界区(即操 作共享资源的代码)。 使用Reen…

Px4 V2.4.8飞控Mavlink命令控制说明

首先&#xff0c;可以使用两种方法连接飞控&#xff0c;使用虚拟机&#xff08;LINUX&#xff09;或使用地面站&#xff08;QGC&#xff09;连接。 在px4的代码文件位置打开命令终端&#xff0c;输入连接命令&#xff1a; ./Tools/mavlink_shell.py 在控制台使用help来获取所有…

【Vue3】h、ref:vue3的两个新特性(重要)-h和ref

h、ref&#xff1a;vue3的两个新特性-重要 h 函数&#xff08; createElement&#xff09;ref 函数总结 在 Vue 3 中&#xff0c;h 和 ref 是两个非常重要的函数&#xff0c;它们在框架的运行和组件的创建中扮演着关键角色。在 Vue 3 中&#xff0c;这两个函数是构建现代 Vue 应…

MySQL8安装与卸载

1.下载mysql MySQL :: Download MySQL Community Serverhttps://dev.mysql.com/downloads/mysql/ 2.解压mysql安装包 解压到自己定义的目录&#xff0c;这里解压就是安装&#xff0c;解压后的路径不要有空格和中文。 3.配置环境变量 配置环境变量可以方便电脑在任何的路径…

简洁安装配置在Windows环境下使用vscode开发pytorch

简洁安装配置在Windows环境下使用vscode开发pytorch 使用anaconda安装pytorch&#xff0c;通过vscode集成环境开发pytorch 下载 anaconda 下载网址&#xff0c;选择对应系统的版本 https://repo.anaconda.com/archive/ windows可以选择Anaconda3-2024.10-1-Windows-x86_64.e…

25.Java JUC 引入(进程与线程、线程的状态、并发与并行、管程、用户线程与守护线程)

一、JUC 简介 JUC 是 java.util.concurrent 工具包的简称&#xff0c;这是一个处理线程的工具包&#xff0c;从 JDK1.5 开始出现 二、进程与线程 1、基本介绍 &#xff08;1&#xff09;进程 进程是计算机中的程序关于某数据集合上的一次运行活动&#xff0c;是系统进行资源…

使用 Jupyter Notebook:安装与应用指南

文章目录 安装 Jupyter Notebook1. 准备环境2. 安装 Jupyter Notebook3. 启动 Jupyter Notebook4. 选择安装方式&#xff08;可选&#xff09; 二、Jupyter Notebook 的基本功能1. 单元格的类型与运行2. 可视化支持3. 内置魔法命令 三、Jupyter Notebook 的实际应用场景1. 数据…

快速理解MIMO技术

引言 在无线通信领域&#xff0c;MIMO&#xff08;Multiple-Input Multiple-Output&#xff0c;多输入多输出&#xff09;技术是一项革命性的进步&#xff0c;它通过在发射端和接收端同时使用多个天线&#xff0c;极大地提高了通信系统的容量、可靠性和覆盖范围。本文简要阐释其…

unity学习3:如何从github下载开源的unity项目

目录 1 网上别人提供的一些github的unity项目 2 如何下载github上的开源项目呢&#xff1f; 2.1.0 下载工具 2.1.1 下载方法1 2.1.2 下载方法2&#xff08;适合内部项目&#xff09; 2.1.3 第1个项目 和第4项目 的比较 第1个项目 第2个项目 第3个项目 2.1.4 下载方法…

npm install --global windows-build-tools --save 失败

注意以下点 为啥下载windows-build-tools&#xff0c;是因为node-sass4.14.1 一直下载不成功&#xff0c;提示python2 没有安装&#xff0c;最终要安装这个&#xff0c;但是安装这个又失败&#xff0c;主要有以下几个要注意的 1、node 版本 14.21.3 不能太高 2、管理员运行 …

十二、Vue 路由

文章目录 一、简介二、安装与基本配置安装 Vue Router创建路由实例在应用中使用路由实例三、路由组件与视图路由组件的定义与使用四、动态路由动态路由参数的定义与获取动态路由的应用场景五、嵌套路由嵌套路由的概念与配置嵌套路由的应用场景六、路由导航<router - link>…

NLP 中文拼写检测纠正论文-08-Combining ResNet and Transformer

拼写纠正系列 NLP 中文拼写检测实现思路 NLP 中文拼写检测纠正算法整理 NLP 英文拼写算法&#xff0c;如果提升 100W 倍的性能&#xff1f; NLP 中文拼写检测纠正 Paper java 实现中英文拼写检查和错误纠正&#xff1f;可我只会写 CRUD 啊&#xff01; 一个提升英文单词拼…

深度学习中的离群值

文章目录 深度学习中有离群值吗&#xff1f;深度学习中的离群值来源&#xff1a;处理离群值的策略&#xff1a;1. 数据预处理阶段&#xff1a;2. 数据增强和鲁棒模型&#xff1a;3. 模型训练阶段&#xff1a;4. 异常检测集成模型&#xff1a; 如何处理对抗样本&#xff1f;总结…

儿童坐姿矫正器是如何实现语音提示功能?

儿童坐姿不正确&#xff0c;不仅影响他们的体态美观&#xff0c;更关乎其身体健康与成长发育。长期以往&#xff0c;可能会导致脊柱侧弯、近视加深等一系列健康问题。家长应当对此给予足够重视&#xff0c;及时纠正孩子们的坐姿习惯。 为了改善这一状况&#xff0c;可以从这方…

C++ 的 error_code 之三:自定义 error_condition

1 自定义 error_condition ​ 上一节我们实现了自定义的 error_code&#xff0c;通过定制 std::error_code 的内部机制&#xff0c;支持与系统相关错误码的隐式转换和直接比较&#xff0c;这一节我们再考虑一种情况。假设我们的支持库要同时支持 Windows 和 Linux 系统&#x…

pytdx,取市场股票列表,get_security_list,start参数为8000时,数据获取失败,导致无法获取全量数据的BUG修正

连接&#xff0c;普通行情&#xff08;服务器&#xff09;&#xff0c;想获取所有的深市A股的股票列表 调用get_security_list函数&#xff0c;但是发现&#xff0c;start为8000开始数据取不到了 于是&#xff0c;打开pytdx的源码 .conda/envs/qmt_mini/Lib/site-packages/p…

【蓝桥杯——物联网设计与开发】Part1:GPIO

目录 一、GPIO输出——LED &#xff08;1&#xff09;资源介绍 &#x1f505;原理图 &#x1f505;驱动原理 &#xff08;2&#xff09;STM32CubeMX 软件配置 &#xff08;3&#xff09;代码编写 &#x1f7e2;️main 函数 &#xff08;4&#xff09;实验现象 二…

如何得到深度学习模型的参数量和计算复杂度

1.准备好网络模型代码 import torch import torch.nn as nn import torch.optim as optim# BP_36: 输入2个节点&#xff0c;中间层36个节点&#xff0c;输出25个节点 class BP_36(nn.Module):def __init__(self):super(BP_36, self).__init__()self.fc1 nn.Linear(2, 36) # …

小程序发版后,强制更新为最新版本

为什么要强制更新为最新版本&#xff1f; 在小程序的开发和运营过程中&#xff0c;强制用户更新到最新版本是一项重要的策略&#xff0c;能够有效提升用户体验并保障系统的稳定性与安全性。以下是一些主要原因&#xff1a; 1. 功能兼容 新功能或服务通常需要最新版本的支持&…

Servlet解析

概念 Servlet是运行在服务端的小程序&#xff08;Server Applet)&#xff0c;可以处理客户端的请求并返回响应&#xff0c;主要用于构建动态的Web应用&#xff0c;是SpringMVC的基础。 生命周期 加载和初始化 默认在客户端第一次请求加载到容器中&#xff0c;通过反射实例化…