数据库锁机制

news2024/10/7 12:19:23

锁机制

  • 1. 概述
  • 2. 并发事务的不同场景
    • 2.1 读-读情况
    • 2.2 写-写情况
    • 2.3 读-写或写-读情况
      • 2.3.1 方案一:读事务使用MVCC(多版本并发控制),写事务加锁
      • 2.3.2 方案二:读、写事务均加锁
  • 3. 锁分类
    • 3.1 从数据操作类型:读锁、写锁
    • 3.2 从数据操作粒度:表级锁、页级锁、行锁
      • 3.2.1 表级锁(Table Lock)
        • 表级别的S锁、X锁
        • 意向锁(Intention Lock)
        • 自增锁(Auto-Inc Lock)
        • 元数据锁(Meta Data Lock)
      • 3.2.2 行锁(Row Lock)
        • 记录锁(Record Lock)
        • 间隙锁(Gap Lock)
        • 临键锁(Next-Key Lock)
        • 插入意向锁(Insert Intention Lock)
      • 3.2.3 页锁
    • 3.3 从对待锁的态度:乐观锁、悲观锁
      • 3.3.1 悲观锁
      • 3.3.2 乐观锁
        • 版本号机制
    • 3.4 从加锁的方式:显式锁、隐式锁
      • 3.4.1 显式锁
      • 3.4.2 隐式锁
  • 4. 死锁
    • 4.1 死锁
    • 4.2 死锁产生的必要条件
    • 4.3 如何处理死锁
      • 4.3.1 方式一:使用超时机制
      • 4.3.2 方式二:使用死锁检测机制
    • 4.4 如何避免死锁问题

1. 概述

  • 锁机制是保证事务隔离性的根本;
  • 计算机通过锁机制协调多进程/多线程并发访问相同资源的问题;
  • 锁机制保证同一时刻共享资源只能被某一进程/线程访问,以此保证数据的一致性和完整性;
  • 从数据库角度而言,共享资源除了硬件资源以外还有表数据,为保证表数据的一致性和完整性,就必须引入锁机制,对并发操作进行控制;
  • 锁机制会导致锁冲突甚至死锁的发生,及其影响并发操作的性能;

2. 并发事务的不同场景

2.1 读-读情况

  • 多个事务同时读取相同记录,并不会对记录本身造成影响,所以无需进行特殊处理;

2.2 写-写情况

  • 多个事务均要对相同记录进行修改,此时可能会发生“脏写”问题;
  • 所有隔离级别都解决了“脏写”问题,通过对事务加锁的方式实现,同一时刻只能允许一个事务执行,其他事务排队等待;
  • 对于锁机制,每个事务均对应一个锁结构(内存级别)与记录关联,包括事务信息以及该事务是否需要排队等待等信息:
    在这里插入图片描述
  • 事务对应锁结构中is_waiting有两种取值:1)is_waiting=false,说明该事务获取锁成功,可以继续执行事务;2)is_waiting=true,说明该事务获取锁失败,期望操作的记录已经被加锁,当前事务需要排队等待;

2.3 读-写或写-读情况

  • 读-写或写-读情况,即多个事务中既有数据读取事务,也有数据写入事务,此时可能会发生“脏读”、“不可重复读”以及“幻读”问题;
  • 未解决上述并发事务问题,MySQL提供两种方案:1)读事务使用MVCC(多版本并发控制),写事务加锁;2)读、写事务均加锁;

2.3.1 方案一:读事务使用MVCC(多版本并发控制),写事务加锁

  • 此方案适用于读、写事务不会冲突,可同时进行的情况,并发性能较高;
  • 写事务需要对最新数据进行修改,所以需要加锁,避免其他事务的干扰;
  • 此情况下读事务只能读取到其他事务已提交的数据,因此对于读事务而言其他事务对记录的修改和记录的旧版本不冲突,所以可以直接读取旧版本数据;
  • MVCC做法:1)生成ReadView,通过ReadView确定符合条件的记录版本,记录的历史版本通过undo日志构建;2)读事务只能看到生成ReadView之前已提交的数据;
    在这里插入图片描述

2.3.2 方案二:读、写事务均加锁

  • 此方案适用于读、写事务冲突,不能同时进行的情况,并发性能较低;
  • 此情况下读事务需要获取最新数据,所以需要避免其他事务的干扰,因此需要加锁;
  • 事务通过对数据记录加锁保证数据一致性,避免发生“脏读”、“不可重复读”以及“幻读”问题;

3. 锁分类

3.1 从数据操作类型:读锁、写锁

  • 读锁:readLock,也称共享锁:Shared Lock,S Lock;写锁:writeLock,也称排他锁:Exclusive Lock,X Lock;
  • 对于读事务(查询操作),可加共享锁或排他锁;
  • 对于写事务(增删改操作),可加排他锁;
  • 读写锁互斥关系:
    1)多个读锁之间不会互斥;
    2)读锁-写锁之间会互斥;
    3)写锁-写锁之间会呼出;
  • 如果数据已经加锁,当前事务无法获取锁,则默认进入阻塞状态,通过innodb_lock_wait_timeout参数进行控制。MySQL8.0新特性可在加锁操作后添加NOWAIT或SKIP LOCAKED参数执行不同的选择。
  • 读事务加锁方式:
    1)读锁:select ... for share;
    2)写锁:select ... for update
  • InnoDB引擎下,读写锁既可以加在表上,也可加在行上;

3.2 从数据操作粒度:表级锁、页级锁、行锁

  • MyISAM引擎只支持表级锁,InnoDB引擎支持表级锁、行锁;
  • 表级锁对应操作粒度较粗,行锁对应操作粒度较细;
  • 操作粒度越细,并发性能越好,但较耗费资源;

3.2.1 表级锁(Table Lock)

  • 最基本的锁策略,不依赖于存储引擎;
  • 表级锁对应资源开销最小,并发性能最低;
  • 表级锁可避免死锁问题;

表级别的S锁、X锁

  • 对于InnoDB引擎而言,一般不会使用表级别的S锁、X锁。
  • 在某事务执行DDL操作,而其他事务在执行DML操作时,会触发表锁,该过程是在server层通过元数据锁实现的;
  • 如果仅使用表级别的S锁、X锁,则使用MyISAM引擎即可;
  • 添加表级别的S锁、X锁方式:
    1)添加S锁:lock tables 表名 read
    2)添加X锁:lock tables 表名 write
  • 释放表锁:unlock tables
  • 查看表锁:show open tables
  • 互斥关系:
    在这里插入图片描述

意向锁(Intention Lock)

  • InnoDB支持多粒度锁,特殊情境下允许行锁和表锁共存;
  • 意向锁是一种表锁,允许和行锁共存;
  • 意向锁分类:意向共享锁IS锁、意向排他锁IX锁;
  • 当为数据表添加行锁之后,数据库会自动为对应数据页或数据表添加相应意向锁,如此其他事务想要添加表锁就会进入阻塞状态;
  • 互斥关系:1)意向锁之间不互斥;2)IS锁与表级S锁不互斥,其他意向锁与表级S锁或X锁互斥;
  • 总结:
    在这里插入图片描述

自增锁(Auto-Inc Lock)

  • 插入数据的方式:1)简单插入:事先知道要插入的数据数量;2)批量插入:事先不知道要插入的数据数量;3)混合模式插入:批量插入数据,有些指定了字段序号,有些未指定;
  • 对于数据表,如果有字段设置有AUTO_INCREMEN约束,则向该表插入数据时,会添加表级锁,称为自增锁;
  • 自增锁并发性能较差,InnoDB通过innodb_autoinc_lock_mode参数提供不同的锁定机制,提高性能:
    1)innodb_autoinc_lock_mode = 0(“传统”锁定模式):在此锁定模式下,所有类型的insert语句都会获得一个特殊的表级AUTO-INC锁,用于插入具有AUTO_INCREMENT列的表。
    2)innodb_autoinc_lock_mode = 1(“连续”锁定模式): MySQL 8.0 之前的默认模式。在这个模式下,批量插入仍然使用AUTO-INC表级锁,并保持到语句结束。而对于简单插入,则通过在 mutex(轻量锁) 的控制下获得所需数量的自动递增值来避免表级AUTO-INC锁, 它只在分配过程的持续时间内保持,而不是直到语句完成。
    3)innodb_autoinc_lock_mode = 2(“交错”锁定模式): MySQL 8.0 开始,交错锁模式是默认设置。在此锁定模式下,自动递增值保证在所有并发执行的所有类型的insert语句中是唯一且单调递增的。但是,由于多个语句可以同时生成数字(即,跨语句交叉编号),为任何给定语句插入的行生成的值可能不是连续的。

元数据锁(Meta Data Lock)

  • 简称MDL锁,用于保证表结构与数据的一致性;
  • MDL锁在server层实现;
  • 当某事务要对数据表进行增删改查操作时,会自动添加MDL读锁;当某事务要对数据表结构进行修改时,会自动添加MDL写锁;
  • MDL读锁之间不互斥,但MDL读-写锁之间是互斥的;

3.2.2 行锁(Row Lock)

  • 也称为记录锁(Record Lock),即对符合条件的记录加锁;
  • MySQL只在引擎层实现了行级锁;
  • MyISAM与InnoDB的区别:1)InnoDB支持事务;2)InnoDB支持行锁;
  • 行锁优缺点:
    1)优点:锁定粒度小,发生锁冲突概率低,提高并发性能;
    2)缺点:维护锁的开销较大,加锁速度慢,容易发送死锁问题;

记录锁(Record Lock)

  • 官方名称:LOCK_REC_NOT_GAP;
  • 仅对满足条件的唯一记录进行加锁;
  • 记录锁也分:读锁、写锁;
  • 读锁之间兼容,其他情况互斥;

间隙锁(Gap Lock)

  • 官方名称:LOCK_GAP;
  • 事务隔离级别为可重复读时,可通过事务加锁的方式解决脏读、不可重复读以及幻读问题;
  • 需要注意,加锁方式解决幻读问题时会存在一些问题,事务读取数据时,幻影记录并未存在,无法锁定幻影记录;
  • 数据库引入间隙锁来解决幻读问题,即GAP锁的提出仅是为了防止插入幻影记录
  • GAP锁与其他记录锁或间隙锁是不互斥的;
  • 间隙锁会导致发生死锁问题

临键锁(Next-Key Lock)

  • 官方名称:LOCK_ORDINARY;
  • 临键锁本质是记录锁和间隙锁的合体,既能锁定对应记录,也能防止在该记录之前的间隙插入记录;
  • 事务隔离级别为可重复读时,InnoDB引擎默认使用的锁机制即为临键锁;

插入意向锁(Insert Intention Lock)

  • 官方名称:LOCK_INSERT_INTENTION;
  • 插入意向锁为行锁,本质是间隙锁;
  • 间隙锁可以防止其他事务在锁定的间隙中插入数据,插入意向锁为插入数据事务对应的锁结构;
  • 插入意向锁之间不会互斥;
  • 插入意向锁和其他锁不互斥;

3.2.3 页锁

  • 对数据页进行加锁,锁定粒度介于表锁与行锁之间;
  • 页锁也会发生死锁现象;
  • 页锁的开销介于表锁和行锁之间;
  • 锁空间大小是有限的,如果某个层级的锁数量超过当前层阈值,则会对锁进行自动升级。如此操作会降低内存开销,但降低了并发性能;

3.3 从对待锁的态度:乐观锁、悲观锁

  • 乐观锁、悲观锁只是针对锁的一种设计思想,各自有对应的具体实现;

3.3.1 悲观锁

  • 思想:每次假设最坏的情况,即假设每个事务都会修改数据,所以每个事务一来就对数据加锁,其他事务进行等待;
  • 数据库中涉及的表锁、行锁等都是悲观锁的具体实现;
  • 悲观锁适用于频繁写操作的情况;

3.3.2 乐观锁

  • 思想:对并发事务保持乐观态度,认为同一数据的并发事务并不会经常发生,因此事务刚开始并不会进行加锁,而是真正要修改数据时才去判断是否发生了并发冲突;
  • 乐观锁在程序级别通过代码实现,而不会通过数据库底层;
  • 乐观锁的实现方案:1)版本号机制;2)CAS机制;
  • 乐观锁不会发生死锁问题;
  • 乐观锁适用于频繁读操作的情况;

版本号机制

  • 对数据添加版本号字段version,version有初始值;
  • 事务在操作数据时,同时获取数据对应版本号,只有当事务版本号version大于最开始获取的数据版本号version时才能完成数据修改的提交;

3.4 从加锁的方式:显式锁、隐式锁

3.4.1 显式锁

  • 通过特定语句加的锁,称为显式锁;如
    在这里插入图片描述

3.4.2 隐式锁

在这里插入图片描述

4. 死锁

4.1 死锁

  • 两个事务均持有对方需要的锁,且在等待对方释放锁,而事务自身均不会释放自己持有的锁。此时两个事务进入循环等待,均无法继续执行。
  • 产生死锁的关键在于:两个事务加锁的顺序不一致;

4.2 死锁产生的必要条件

  • 至少存在两个事务;
  • 每个事务都持有锁,并需要申请新的锁;
  • 锁资源同时只能被同一个事务持有;
  • 事务之间因为持有锁和申请锁导致彼此循环等待;

4.3 如何处理死锁

4.3.1 方式一:使用超时机制

  • 事务如果无法成功获取锁,则进入等待,直到等待超时;
  • 超时时间通过innodb_lock_wait_timeout参数设置;
  • 如果事务等待超时,则将其回滚;
  • 缺点:不适用于在线任务;

4.3.2 方式二:使用死锁检测机制

  • InnoDB使用wait-for graph算法主动进行死锁检测;
    在这里插入图片描述
    在这里插入图片描述

  • 事务一旦无法成功获取锁,则主动进行死锁检测,检测是否是自己的加入导致死锁的发生;

  • 一旦检测到死锁,InnoDB选择回滚undo量最小的事务,其他事务继续执行;

  • 缺点:对于并发事务量较大的业务,死锁检测耗时较大;

4.4 如何避免死锁问题

在这里插入图片描述
参考《尚硅谷:康师傅》

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

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

相关文章

1.Docker概念

文章目录 Docker概念Docker容器与虚拟机的区别内核中的2个重要技术Linux Namespace的6大类型docker三个重要概念部署Dockeryum安装二进制安装 Docker 概念 docker是一个开源的应用容器引擎,基于go语言开发并遵循了apache2.0协议开源。docker可以让开发者打包他们的…

【PostgreSQL内核学习(三)—— 查询重写】

查询重写 查询重写系统规则视图和规则系统ASLO型规则的查询重写规则系统与触发器的区别 查询重写的处理操作定义重写规则删除重写规则对查询树进行重写 声明:本文的部分内容参考了他人的文章。在编写过程中,我们尊重他人的知识产权和学术成果&#xff0c…

王道计算机网络学习笔记(4)——网络层

前言 文章中的内容来自B站王道考研计算机网络课程,想要完整学习的可以到B站官方看完整版。 四:网络层 ​​​​​​​​​​​​​​在计算机网络中,每一层传输的数据都有不同的名称。 物理层:传输的数据称为比特(Bi…

宝塔的Redis绑定IP

宝塔安装Redis 软件商店搜索Redis 连接宝塔面板的redis服务器失败的解决办法 检查Linux是否放行6379端口修改Redis绑定IP检查阿里云/腾讯云的防火墙策略是否放行6379端口 1.bind 127.0.0.1 修改为 bind 0.0.0.0 127.0.0.1 表示只允许本地访问,无法远程连接 0.0.0.0 表…

基于Python的用户登录和密码强度等级测试|Python小应用

前言 那么这里博主先安利一些干货满满的专栏了! 这两个都是博主在学习Linux操作系统过程中的记录,希望对大家的学习有帮助! 操作系统Operating Syshttps://blog.csdn.net/yu_cblog/category_12165502.html?spm1001.2014.3001.5482Linux S…

Micro-app vue3+vite+ts用法

前言: 微前端的概念是由ThoughtWorks在2016年提出的,它借鉴了微服务的架构理念,核心在于将一个庞大的前端应用拆分成多个独立灵活的小型应用,每个应用都可以独立开发、独立运行、独立部署,再将这些小型应用融合为一个…

文库小程序在线阅读下载文档模板流量主小程序

一、什么是文库小程序? 文库小程序连接流量主,具体流程是粉丝进入小程序下载文档模板,下载前需要看广告,阅读后可以免费下载文档模板。具体的小程序演示请参见抖音云云文库 二、文库小程序的应用范围 小程序主要实现文档共享功能…

Redis Linux安装

Redis版本下载,版本地址http://download.redis.io/releases/ 点击跳转 新建文件夹 mkdir /usr/local/redis 上传压缩包,并使用命令解压tar -zxvf redis-6.2.8.tar.gz (redis-6.2.8.tar.gz为安装包) 安装依赖 yum install gcc-c 编译 make 安装 make install 修改配置 …

概率论和随机过程的学习和整理20:条件概率我知道,但什么是条件期望?可用来解决递归问题

目录 1 目标问题: 什么是条件期望? 条件期望有什么用? 2 条件期望,全期望公式 3 条件期望,全期望公式 和 条件概率,全概率公式的区别和联系 3.1 公式如下 3.2 区别和联系 3.3 概率和随机过程 4 有什…

Zabbix“专家坐诊”第200期问答汇总

问题一 Q:想请问下大佬们,我们zabbix最近有误告警的情况,这个怎么排查呢? 用了proxy,我看了proxy和server的日志,除了有慢查的日志,其它没有异常日志输出。 A:看下这个unreachable的…

首次与电商平台战略签约 第一三共与阿里健康达成战略合作

7月18日,阿里健康与第一三共在杭州正式签署战略合作协议。双方宣布将在此前合作基础上,全面深化心脑血管、风湿骨外科等疾病领域的合作深度,探索以患者为中心、以数字化为驱动力的创新型医药健康服务模式。据悉,此次合作是第一三共…

椒图--分析中心和后台管理中心

护网的时候我们要把右边的开关开启。开启就会对系统全量的记录,包含有网络行为日志,就会检测我们服务器里面的链接,端口箭头,内内网暴露的链接;进程操作日志,就可以看我们系统创建了哪些进程,就…

融云出海:不止假发出口和四卡四待手机,「非洲市场」的参差与机遇

↑ 点击预约“融云北极星”直播↑ 点击预约“实时社区”直播 比白皮书更精炼省流,比图谱更实用有效。 融云《社交泛娱乐出海作战地图》,被多位大咖标记为出海人必备工作手册。针对地图的核心模块,我们推出了系列解读文章,更详尽…

Redis数据持久化的两种方式

说明:Redis数据是存储在内存中的,Redis服务被关闭,数据是会被清除的。但Redis有数据持久化机制,在默认情况下,停止Redis服务会触发数据持久化机制,将数据保存下来,在下次启动时再读取出来。 Re…

解决spring security No AuthenticationProvider found for com.问题

No AuthenticationProvider found for com.xxx.xx 原因 当你验证过,后记得这个这里返回true。不然,就会出现既没有异常,又没验证返回通过的中间尴尬状态,security会当做没有验证通过来处理。 修改

HCIA-存储虚拟化

1、虚拟化概述 KVM是所有云平台的底座,虚拟化是所有云的基础,虚拟化只提供基础架构,云可以提供服务。 CNA是个定制的欧拉系统EulerOS,基于centos内核只保留和虚拟化相关的代码,CNA默认已经部署好kvm虚拟化的软件。CNA…

Visutal Studio2022 如何使用Github copilot

visual studio 2019 升级最新版本的2019也并没有搜索到,直接升级到visual studio 2022,看发布介绍也是2022的copilot Copilot 是一款由 OpenAI 开发的基于 GPT 模型的代码生成工具,可帮助开发者更快地编写代码。如果想在 Visual Studio 中使…

基于大模型的属性操作生成高效训练数据

概述 这篇论文的研究背景是关于利用大型语言模型(LLM)生成高效训练数据的方法。 以往的方法通常是通过LLM生成新的数据,但缺乏对生成数据的控制,这导致了生成数据的信息不足以反映任务要求。本文提出了一种基于LLM的属性操作生成方法,通过精…

如何应对客户报价要求过低的情况?这些方案帮你化解危机!

有个客户在寄样品之前让报价,并且要求承诺价格必须低于15美金,业务员同意了,让客户把样板安排寄到中国,但是收到样品后发现客户的样品在侧面还有一块突出的部分,所以15美金太低了,无论如何也得18美金&#…

计组4——总线Plus IO

(CPU外部的)总线 用于连接computer3大模块(MC/GPUIO) CPU内部的片内总线判优由时序逻辑实现 composition& priority-judging 通信方式 CPU内部的片内总线用于取指、译码、执行、中断的数据通信; IO 总线分为控制线、数据线和地址线,对IO设备的…