数据库锁机制

锁机制

  • 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.mzph.cn/news/3541.shtml

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

相关文章

MySQL学习笔记

文章目录 1、登录2、查看数据库3、连接数据库4、查看表5、退出6、创建/删除数据库7、创建表8、数据类型9、查看表中的内容10、向表中插入数据11、约束主键:主键(PRIMARY KEY)作为数据表中一行数据的唯一标识符,在一张表中通过主键…

e2e测试框架之Cypress

谈起web自动化测试,大家首先想到的是Selenium!随着近几年前端技术的发展,出现了不少前端测试框架,这些测试框架大多并不依赖于Selenium,这一点跟后端测试框架有很大不同,如Robot Framework做Web自动化测试本…

CVE-2013-4547

CVE-2013-4547 一、环境搭建二、漏洞原理三、漏洞复现 一、环境搭建 如下介绍kali搭建的教程 cd ~/vulhub/nginx/CVE-2013-4547 // 进入指定环境 docker-compose build // 进行环境编译 docker-compose up -d // 启动环境docker-compose ps使用这条命令查看当前正在运…

Redis学习(三)持久化机制、分布式缓存、多级缓存、Redis实战经验

文章目录 分布式缓存Redis持久化RDB持久化AOF持久化 Redis主从Redis数据同步原理全量同步增量同步 Redis哨兵哨兵的作用和原理sentinel(哨兵)的三个作用是什么?sentinel如何判断一个Redis实例是否健康?master出现故障后&#xff0…

AI 智能对话 - 基于 ChatGLM2-6B 训练对话知识库

前情提要 怎么将 AI 应用到工作中呢?比如让 AI 帮忙写代码,自己通过工程上的思维将代码整合排版,我挺烦什么代码逻辑严谨性的问题,但是我又不得不承认这样的好处,我们要开始将角色转换出来,不应该是一个工…

Ceph部署

目录 1、存储基础 单机存储设备 单机存储的问题 分布式存储(软件定义的存储 SDS) 分布式存储的类型 2、Ceph 简介 3、Ceph 优势 4、Ceph 架构 5、Ceph 核心组件 Pool中数据保存方式支持两种类型: Pool、PG 和 OSD 的关系&#xff…

功能丰富的 Markdown 笔记工具:FSNotes Mac中文版图文安装教程

FSNotes Mac版是Mac平台上一款纯文本笔记本管理器,FSNotes for mac中文版支持Markdown、RTF等格式,轻松查看和编辑数据,还可以将数据存储在文件系统中,同时具备iCloud同步功能,使用非常便捷。 FSNotes for mac官方介绍…

自动化测试转型挑战及其解决方案

目录 前言: 自动化测试挑战 选择合适的自动化测试方法 选择正确的自动化工具 整理数据 何时开始和停止 如何克服挑战 前言: 自动化测试的转型是许多组织在提高测试效率和质量方面的重要举措。然而,这个转型过程中可能会面临一些挑战。…

Java 装箱拆箱原理 包装类型缓存池

JAVA中的基本数据类型 byteshortintlongfloatdoublebooleanchar 为了让上述基本数据类型可以转为对象,Java在1.5推出了一系列包装类,基本类和包装类互相转换的过程,称为装箱和拆箱 缓存池 缓存池也叫常量池。它是事先存储一些常量数据用以…

优化营商环境:构建智能营销平台,助力企业经营发展

对于企业来说,没有了客户,就像身体没有了血液,将失去生命力和活力,续存难发展更难。区域产业又是由一个个企业集聚而形成,企业的成败也就决定着区域产业的兴衰。 在当今竞争激烈的商业环境中,传统的销售手段…

MongoDB初体验-安装使用教程2023.7

前言:博主第一次接触MongoDB,看了一圈网上现有的教程,不是缺少细节就是有问题没交代清楚,特整理了一下自己安装运行的过程,从下载安装到开机自启,全程细节齐全、图文并茂、简单易懂。 目录 1. 从官网下载2…

基于遗传算法的新能源电动汽车充电桩与路径选择MATLAB程序

主要内容: 根据城市间的距离,规划新能源汽车的行驶路径。要求行驶距离最短。 部分代码: %% 加载数据 %%遗传参数 load zby;%个城市坐标位置 NIND50; %种群大小 MAXGEN200; Pc0.9; %交叉概率 Pm0.2; %变异概率 GGAP0.…

巩固一下NodeJs

1、初始化(确保当前电脑有node环境) npm init 2、安装express npm i expressnpm i ws文件结构 3、编写相关代码启动node服务(server.js) //导入下列模块,express搭建服务器,fs用来操作文件、ws用来实现webscoket const express require("expr…

C++进阶—C++11新特性(移动语义右值引用可变参数模板lambda表达式function包装器bind函数)

目录 0. C11简介 1. 统一的列表初始化 1.1 {}初始化 1.2 std::initializer_list 2. 声明 2.1 auto 2.2 decltype 2.3 nullptr 3. 范围for循环 4. 智能指针 5. STL中一些变化 6. 右值引用和移动语义 6.1 左值引用和右值引用 6.2 左值引用与右值引用比较 6.3 右值…

PSP - Jackhmmer 搜索 EMBL 序列数据库的相似序列

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/131817060 EMBL (European Molecular Biology Laboratory,欧洲分子生物实验室):EMBL 数据库是一个由欧洲生物信息学研究所…

springboot与rabbitmq的整合【演示5种基本交换机】

前言: 👏作者简介:我是笑霸final,一名热爱技术的在校学生。 📝个人主页:个人主页1 || 笑霸final的主页2 📕系列专栏:后端专栏 📧如果文章知识点有错误的地方,…

【0】冒泡排序

前言 通过函数模板技术设计一个冒泡排序算法,领悟泛型编程的思想和冒泡排序的思想,然后使用QTest测试各种输入值,养成先写测试代码,后写程序代码的习惯 0x0 编写一个int版本的冒泡函数 1.不管要排序的数组长度多长,外…

CASAIM与大疆达成全自动化测量技术合作,CASAIM IS全自动化蓝光测量仪实现无人机叶片全尺寸检测及质量控制

近期,CASAIM与大疆达成全自动化测量技术合作,CASAIM IS全自动化蓝光测量仪实现无人机叶片全尺寸检测及质量控制。 无人机行业在过去几年里取得了迅猛发展,大疆是全球领先的无人飞行器控制系统及无人机解决方案的研发商和生产商,客…

Spring-AOP(面向切面)

Spring-AOP(面向切面) 场景模拟(计算器) 功能接口 public interface Calculator {int add(int i, int j);int minus(int i, int j);int multiply(int i, int j);int div(int i, int j); }实现类 public class CalculateLogImpl implements Calculator {Overridepublic int …

PALO ALTO NETWORKS 的新一代防火墙如何保护企业安全

轻松采用创新技术、阻止网络攻击得逞并专注更重要的工作 IT 的快速发展已改变网络边界的面貌。数据无处不在,用户可随时随地从各类设备访问这些数据。同时,IT 团队正在采用云、分析和自动化来加速新应用的交付以及推动业务发展。这些根本性的转变带来了…