MySQL锁篇

2023-05-16

文章目录

      • 说明:
      • 锁篇
          • 一、MySQL有那些锁?
          • 二、MySQL 是怎么加锁的?
          • 三、update 没加索引会锁全表?
          • 四、MySQL 记录锁+间隙锁可以防止删除操作而导致的幻读吗?
          • 五、MySQL 死锁了,怎么办?
          • 六、字节面试:加了什么锁,导致死锁的?

说明:

此类文章是为小林coding的图解MySQL,所简写,目的在于大家更快抓到小林文章的重点
本文全部由我简化,但是其中有部分引用小林的文章内容
希望大家掌握精髓,构建知识体系和知识框架

锁篇

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZLBwp08k-1677200893814)(../my_images/1e37f6994ef44714aba03b8046b1ace2.png)]

一、MySQL有那些锁?

全局锁

全局锁主要应用于做全库逻辑备份

缺点是:无法更新数据,会造成业务停滞,不过可重复读隔离级别和MVCC解决了这个问题
备份数据库的工具是 mysqldump,在使用 mysqldump 时加上 –single-transaction 参数的时候,就会在备份数据库之前先开启事务。这种方法只适用于支持「可重复读隔离级别的事务」的存储引擎。

# 使用全局锁
flush tables with read lock # 整个数据库就处于只读状态了
# 释放
unlock tables

表级锁

表锁
元数据锁 MDL
意向锁
AUTO-INC锁

# 表锁
# 表级别的共享锁,也就是读锁;
lock tables t_student read;
# 表级别的独占锁,也就是写锁;
lock tables t_stuent write;
# 释放所有锁,当会话退出后,也会释放所有表锁。表锁的颗粒度太大,会影响并发性能,尽量避免使用,InnoDB 牛逼的地方在于实现了颗粒度更细的行级锁。
unlock tables

# 元数据锁,对数据库表进行操作时,会自动给这个表加上 MDL
# 对一张表进行 CRUD 操作时,加的是 MDL 读锁;
# 对一张表做结构变更操作的时候,加的是 MDL 写锁;
# 有读锁时候想要加写锁,是会被堵塞的,直到读锁被释放,才能加上写锁,相反也是
# MDL 是在事务提交后才会释放,这意味着事务执行期间,MDL 是一直持有的。
# 读读写读读...
# 可可堵堵堵...

# 意向锁
# 意向 共享/独占锁 + 共享/独占锁 # 也就是,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。
# 而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的
# select 也是可以对记录加共享锁和独占锁的,锁定读
//先在表上加上意向共享锁,然后对读取的记录加共享锁
select ... lock in share mode;
//先表上加上意向独占锁,然后对读取的记录加独占锁
select ... for update;
# 意向锁的目的是为了快速判断表里是否有记录被加锁。

#AUTO-INC 锁
# 主键自增AUTO_INCREMENT ,主要是通过AUTO-INC 锁实现的
# 执行完插入语句后就会立即释放
# 一个事务在持有 AUTO-INC 锁的过程中,其他事务想要再插入该表,就会被阻塞,为了保证连续递增
# 对大量数据进行插入的时候,会影响插入性能,InnoDB 存储引擎提供了一种轻量级的锁来实现自增
# 给该字段赋值一个自增的值,就把这个轻量级锁释放了,而不需要等待整个插入语句执行完后才释放锁
# InnoDB 存储引擎提供了个 innodb_autoinc_lock_mode 的系统变量,是用来控制选择用 AUTO-INC 锁
# = 0,就采用 AUTO-INC 锁,语句执行结束后才释放锁;
# = 2,就采用轻量级锁,申请自增主键后就释放锁,并不需要等语句执行后才释放。
# = 1
# 	普通 insert 语句,自增锁在申请之后就马上释放
# 	类似 insert … select 这样的批量插入数据的语句,自增锁还是要等语句结束后才被释放
# 当 innodb_autoinc_lock_mode = 2 是性能最高的方式,但是当搭配 binlog 的日志格式是 statement 一起使用的时候,在「主从复制的场景」中会发生数据不一致的问题。
# 当 innodb_autoinc_lock_mode = 2 时,并且 binlog_format = row,既能提升并发性,又不会出现数据一致性问题

表锁和行锁是满足读读共享、读写互斥、写写互斥的

行级锁
MyISAM 引擎并不支持行级锁。

  • Record Lock,记录锁,也就是仅仅把一条记录锁上;
  • Gap Lock,间隙锁,锁定一个范围,但是不包含记录本身;
  • Next-Key Lock:临键锁Record Lock + Gap Lock 的组合,锁定一个范围,并且锁定记录本身。

间隙锁之间是兼容的,即两个事务可以同时持有包含共同间隙范围的间隙锁,并不存在互斥关系,因为间隙锁的目的是防止插入幻影记录而提出的

因为记录锁是会出现不兼容的,而临键锁是Record Lock + Gap Lock 的组合,自然也是会不兼容的,与记录锁一样

一个事务在插入一条记录的时候,该位置已经被其他事务加了间隙锁(包含临键锁),就会发生阻塞,在拥有间隙锁的那个事务提交前,会生成一个插入意向锁
插入意向锁名字虽然有意向锁,但是它并不是意向锁,它是一种特殊的间隙锁,属于行级别锁

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZmmoGp7N-1677200893815)(../my_images/image-20230223084901512.png)]

二、MySQL 是怎么加锁的?

什么 SQL 语句会加行级锁?

普通的 select 语句是不会对记录加锁的,因为它属于快照读,是通过 MVCC(多版本并发控制)实现的。除非加锁定读

update 和 delete 操作都会加行级锁,且锁的类型都是独占锁(X型锁)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6pWX3BwP-1677200893815)(../my_images/image-20230223085937788.png)]

怎么加行级锁的?

加锁的对象是索引,加锁的基本单位是 next-key lock,前开后闭区间
间隙锁是前开后开区间
在能使用记录锁或者间隙锁就能避免幻读现象的场景下, next-key lock 就会退化成退化成记录锁或间隙锁

select * from performance_schema.data_locks\G; 这条语句,查看事务执行 SQL 过程中加了什么锁。

  • 如果 LOCK_MODE 为 X,说明是 next-key 锁;
  • 如果 LOCK_MODE 为 X, REC_NOT_GAP,说明是记录锁;
  • 如果 LOCK_MODE 为 X, GAP,说明是间隙锁;

之后再补充五种不同的请况是如何加行级锁

三、update 没加索引会锁全表?

在 update 语句的 where 条件没有使用索引,就会全表扫描,于是就会对所有记录加上 next-key 锁(记录锁 + 间隙锁),相当于把整个表锁住了

除了 select ... from语句,其他语句都会被锁住不能执行,业务会因此停滞,接下来等着你的,就是老板的挨骂

那 update 语句的 where 带上索引就能避免全表记录加锁了吗?-并不是。
关键还得看这条语句在执行过程种,优化器最终选择的是索引扫描,还是全表扫描,如果走了全表扫描,就会对全表的记录加锁了

如何避免这种事故的发生?

我们可以将 MySQL 里的 sql_safe_updates 参数设置为 1,开启安全更新模式。
update 语句必须满足如下条件之一才能执行成功:

  • 使用 where,并且 where 条件中必须有索引列;
  • 使用 limit;
  • 同时使用 where 和 limit,此时 where 条件中可以没有索引列;
四、MySQL 记录锁+间隙锁可以防止删除操作而导致的幻读吗?

当然了,就像增删改查,都可以防止,查是select … for update ,这都是当前读

举个例子哈,执行了select … for update,就是开启了一个事务,对这个区间的记录加了next-key lock锁

然后执行删除操作,这时候,因为有锁就被阻塞了,加意向锁,进入等待状态

但是记住,一定要检查,这个字段是否加了索引,否则会走全表扫面,锁全表

五、MySQL 死锁了,怎么办?

两个事务,分别执行了select … for update,后执行更新或者删除,创建,就会进入死锁,双方都在等待对方提交事务,无限循环,前提,没开死锁检查

如何避免死锁?

两种策略通过「打破循环等待条件」
数据库层面,两种策略通过「打破循环等待条件」

  • 设置事务等待锁的超时时间,innodb_lock_wait_timeout 是用来设置超时时间的,默认值时 50 秒。
  • 开启主动死锁检测,检测在发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行,将参数 innodb_deadlock_detect 设置为 on,默认就开启
六、字节面试:加了什么锁,导致死锁的?

两个事务,先分别执行了update,再执行insert,出现死锁

update时候是x型意向锁,x型间隙锁

insert时候是x型插入意向锁,x型间隙锁

插入意向锁和间隙锁之间是冲突的

双方都在等待对方的间隙锁释放,造成循环等待
满足了互斥、占有且等待、不可强占用、循环等待

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

MySQL锁篇 的相关文章

  • 映射 mysql 中同一个表的多个值

    您好 我必须使用另一个表中的值 id 获取文本值 表 1 包含值 ID 表 2 包含名称和值 ID 表 1 SEVERITY OCCURENCE DETECTABILITY 2 3 4 表 2 id name value 1 Very Hi
  • Mysql 时间匹配连接

    我有两个表cpuinfo和jobinfo 我想使用这两种数据创建报告 tabes CREATE TABLE cpuinfo id int 11 NOT NULL AUTO INCREMENT usagetime datetime DEFAU
  • 显示标准化数据

    跟进问题 添加 2 个不同表的总和 https stackoverflow com questions 39717541 adding sum from 2 different tables 我创建了3个表 members videos v
  • 海量记录的bulk_create最佳实践

    I use bulk create将 1 mio 记录插入到新表中 需要 80 秒 Django 只使用一个 CPU 核心 大约 25 CPU 但没有一个核心达到 100 我相信有改进的潜力 这是代码 class Stock models
  • 不允许在 php 中连接到此 MariaDB 服务器

    我尝试在 php 中连接远程服务器数据库 但出现以下错误 Host xx xxx xx xx is not allowed to connect to this MariaDB server in 我的连接代码是这样的 servername
  • Windows 8.1 升级后 Apache 无法工作 [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 今天从 Windows 8 升级到 Windows 8 1 后 Apache 不再工作 我上次从 Windows 7 升级到 Window
  • MySQL 和 Hibernate 之间的主键自增由谁负责?

    MySQL CREATE TABLE role id role INT 11 unsigned NOT NULL AUTO INCREMENT PRIMARY KEY id role AUTO INCREMENT 1 休眠 Entity p
  • MySQL 8 用逗号分割字符串并将其转换为JSON ARRAY

    我有以下字符串 a b c d 我想将它转换成一个 json 数组 像这样 a b c d MySQL 8 有什么函数可以实现这个功能吗 Try SELECT CAST CONCAT REPLACE a b c d AS JSON See
  • MySQL“LIKE”搜索不起作用

    我通过 LOAD DATA INFILE 在 MySQL 中导入了一个 txt 数据库 一切似乎都正常 唯一的问题是 如果我使用以下查询在数据库上搜索记录 SELECT FROM hobby WHERE name LIKE Beading
  • PHP 和 MySQL - 高效处理多个一对多关系

    我正在寻求一些有关使用 MySQL 和 PHP 检索和显示数据的最佳方法的建议 我有 3 个表 所有一对多关系如下 Each SCHEDULE有很多覆盖每个覆盖都有很多地点 我想检索这些数据 以便它可以全部显示在单个 PHP 页面上 例如列
  • 如果 Row1 = 值 1,则更新其他行

    我有一个小的 php 脚本 用于访问 mySql 数据库 我想在数据库中插入新记录之前查看该数字 值 1 是否等于数据库中的记录 这也在第 1 行 所以我想 查看传入的电话号码是否等于数据库中的电话号码 如果是这样 则必须保持电话号码相同的
  • 错误代码:1305。函数或过程不存在

    因此 我在 MySQL 中创建一个函数 然后尝试向用户授予使用该函数的权限 但我无法这样做 这就是我正在做的 DELIMITER USE rxhelp36 scbn DROP FUNCTION IF EXISTS businessDayDi
  • MySQL 错误 1172 - 结果包含多行

    在存储过程中运行查询时 我从 MySQL 收到此错误 错误代码 1172 结果包含多行 我理解错误 我正在做一个SELECT INTO var list 因此查询需要返回单行 当我使用LIMIT 1 or SELECT DISTINCT 错
  • 慢速自动增量重置

    我有很多表 由于某些原因 我需要在应用程序启动时调整这些表的自动增量值 我尝试这样做 mysql gt select max id from item max id 97972232 1 row in set 0 05 sec mysql
  • MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。添加了 11 条消息列表。使用emitter.setMaxListeners()来增加限制

    我知道这可能会标记为重复的解决方案 但堆栈溢出的解决方案对我不起作用 Problem node 5716 MaxListenersExceededWarning Possible EventEmitter memory leak detec
  • MySQL 追加字符串

    How can I append a string to the end of an existing table value Let s say I have the table below And let s say that Mari
  • PHP 与 MySQL 查询性能( if 、 函数 )

    我只看到这个artice http www onextrapixel com 2010 06 23 mysql has functions part 5 php vs mysql performance 我需要知道在这种情况下什么是最好的表
  • SQL 最近日期

    我需要在 php 中获取诸如 2010 04 27 之类的日期作为字符串 并在表中找到最近的 5 个日期 表中的日期保存为日期类型 您可以使用DATEDIFF http dev mysql com doc refman 5 1 en dat
  • 内部 while 循环不工作

    这是我项目网页上的代码片段 这里我想显示用户选择的类别 然后想显示属于该类别的主题 在那里 用户可以拥有多个类别 这没有问题 我可以在第一个 while 循环中打印所有这些类别 问题是当我尝试打印主题时 结果只显示一行 但每个类别中有更多主
  • post php mysql 的拆分关键字

    我有一个表存储帖子 ID 它的标签如下 Post id Tags 1 keyword1 keyword2 keyword3 我想循环遍历该表中的每一行并执行以下操作 将关键字1 关键字2 关键字3放入新表中 word id word val

随机推荐

  • 银行排队模拟(队列)

    银行排队模拟程序 队列类Queue ifndef span class token constant QUEUE H span define span class token constant QUEUE H span struct Rec
  • C/C++中struct和class的区别

    目录 struct class struct和class的区别 struct struct是描述一个数据结构的集合 xff0c 像一周有七天 xff0c 你可以把一周看成是一个结构体 xff0c 然后在结构体里面定义一个数组来存放这个七天
  • java枚举(enum)使用详解

    文章目录 前言一 枚举类型定义二 访问成员三 遍历四 在switch xff08 xff09 中使用枚举五 方法1 内置方法1 1 ordinal 用于返回成员的索引1 2 compareTo 用于比较枚举类型中两个成员的索引值1 3 va
  • 分析url从输入到展过程中的页面优化、performance

    浏览器会开启一个线程处理URL请求 url从输入到展示页面的过程 1 输入网址 2 DNS解析 3 建立tcp连接 xff08 请求队列queuing 请求等待stalled 4 客户端发送HTPP请求 5 服务器处理请求 6 服务器响应请
  • 双重锁单例模式

    不忘初心 xff0c 思考梦开始的地方 普通的懒汉式和饿汉式都不用管 简单实现一下线程安全的方式 span class token keyword public span span class token keyword class spa
  • VScode神仙插件,程序员必备

    前言 Visual Studio Code VS Code 是微软2015年推出的一个轻量但功能强大的源代码编辑器 xff0c 基于 Electron 开发 xff0c 支持 Windows Linux 和 macOS 操作系统 它内置了对
  • 【Java】使用Java实现爬虫

    文章目录 使用Java实现爬虫一 HttpClient实现模拟HTTP访问1 1 HttpClient1 2 引入依赖1 3 创建简单的请求操作1 3 1 创建实例1 3 2 Jsoup应用 1 4 爬取过程中可能出现的问题1 4 1 JS
  • STM32 HAL库+ESP8266+华为云物联网平台

    文章内容 xff1a STM32 HAL库通过串口发送AT指令完成与ESP8266的控制实现接入华为云物联网平台 xff0c 并完成基本通信与控制 xff0c 包括设备属性上报和命令下发解析与响应 文末获取 STM32 HAL库 43 ES
  • MySQL事务篇

    文章目录 说明 xff1a 事务篇一 事务隔离级别是怎么实现的 xff1f 二 MySQL 可重复读隔离级别 xff0c 完全解决幻读了吗 xff1f 说明 xff1a 此类文章是为小林coding的图解MySQL xff0c 所简写 xf
  • Android studio TCP网络调试助手应用开发(支持TCP Server与Client切换)

    在前几篇的文章中带大家完成了基于TCP的物联网安卓应用开发 xff0c 教程内容是创建了一个TCP客户端并连接服务器完成数据通信的过程 xff0c 后不久又发布了一个ESP8266创建TCP 服务器与安卓的客户端进行通信的一个文章 xff0
  • 【FreeRTOS】中断管理

    在介绍本文之前 xff0c 向大家推荐个非常容易入门的人工智能学习网站 xff0c 建议点击收藏 目录 xff1a 1 前言2 内核提供两套API2 1 优点2 2 缺点2 3 常用API函数列表2 4 pxHigherPriorityTa
  • 【嵌入式基础】内存(Cache,RAM,ROM,Flash)

    1 前言 最近在看赛普拉斯的一款芯片CYW8019规格书 xff0c 里面有好几个内存的关键字 xff08 如下图的右上方 xff09 xff0c 本文将聊它们的含义和作用 2 Cache Cache是集成在CPU内部的极高速缓存 一般来讲
  • 使用Promise解决多个请求数据并发问题

    首先引用一下阮一峰大佬的一段话 xff1a Promise xff0c 简单说就是一个容器 xff0c 里面保存着某个未来才会结束的事件 xff08 通常是一个异步操作 xff09 的结果 从语法上说 xff0c Promise是一个对象
  • 1. KVM虚拟化学习

    1 什么是虚拟化 虚拟化 xff0c 通过模拟计算机的硬件 xff0c 来实现同一台计算机上运行多个不同的操作系统的既技术 2 为什么要使用虚拟化 为了充分利于资源 xff0c 软件运行环境的隔离 xff0c 只要有虚拟化才能实现 虚拟化提
  • 二次再散列法

    散列表 设所有可能出现的关键字集合记为U 简称全集 实际发生 即实际存储 的关键字集合记为K xff08 K 比 U 小得多 xff09 散列方法是使用函数h将U映射到表T 0 m 1 的下标上 xff08 m 61 O U xff09 这
  • CICD中clang-tidy静态语义检查

    教程 xff1b https hokein github io clang tools tutorial 要用clang tidy首先要在电脑上安装clang tools Linux Ubuntu系统 span class token fu
  • Vscode 设置clang-format

    用户设置与工作空间设置 VS Code提供了两种设置方式 xff1a 用户设置 xff1a 这种方式进行的设置 xff0c 会应用于该用户打开的所有工程 xff1b 工作空间设置 xff1a 工作空间是指使用VS Code打开的某个文件夹
  • 同步异步电机ADRC控制系统仿真

    之前一直使用PI控制器做异步电机矢量控制 xff0c 最近想把ADRC控制也放到异步电机矢量控制上去 xff0c 所以对其进了仿真 xff0c 可遇到了一个一直没有解决掉的问题 xff0c 现记录下来 xff0c 请各位先辈进行指教以及为遇
  • 大疆A型板使用经验分享(八)——FreeRTOS操作系统的使用

    一 freeRTOS操作系统 操作系统 operating system 本质上是一个帮助用户进行功能管理的软件 操作系统运行在硬件之上 为其他工作的软件执行资源分配等管理工作 一般称呼不使用操作系统的单片机开发方式为 裸机开发 当进行裸机
  • MySQL锁篇

    文章目录 说明 xff1a 锁篇一 MySQL有那些锁 xff1f 二 MySQL 是怎么加锁的 xff1f 三 update 没加索引会锁全表 xff1f 四 MySQL 记录锁 43 间隙锁可以防止删除操作而导致的幻读吗 xff1f 五