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锁篇 的相关文章

  • PHP 中的异步数据库/服务调用:Gearman 与 pthreads

    在我们的 LAMP 站点上 我们遇到一些服务必须多次调用数据库才能提取数据的问题 通常在 PHP 中完成此操作的方式 至少我的经验 是串行的 这显然是低效的 我们可以通过使用缓存和聚合一些查询来缓解一些低效率的问题 但在某些情况下我们仍然需
  • 使用 EXPLAIN 进行 MYSQL 存储过程调用

    如何分析和使用 EXPLAIN 来调用我的存储过程 我需要优化查询时间 但是似乎没有地方可以执行 EXPLAIN 调用 proc name 你可以试试 set profiling 1 call proc name show profiles
  • 如何在 Laravel 中编写联合查询?

    我正在使用 laravel 5 0 并且我有 mysql 查询 SELECT surat masuk id surat surat masuk nomor surat FROM surat masuk WHERE EXISTS SELECT
  • MySQL 5左连接未知列

    我有以下查询在 mysql 4 1 中工作 但在 5 0 中不起作用 SELECT FROM email e event email ee LEFT JOIN member m on m email e email WHERE ee ema
  • 执行许多插入重复键更新错误:未使用所有参数

    所以我一直在尝试使用 python 2 7 15 使用 mysql connector 执行此查询 但由于某种原因 它似乎不起作用并且总是返回错误 并非所有参数都被使用 表更新有一个主键 即 ID 这是我尝试运行此 SQL 的查询 sql
  • 更改Docker容器中的mysql密码

    我如何更改 docker 容器中的 root 密码 因为一旦我停止 mysql 服务 容器就会自动停止 我应该停止 mysql 容器并部署一个新容器吗 您可以使用正在运行的容器更改它docker exec session https doc
  • 更新重复密钥上的复合密钥 [重复]

    这个问题在这里已经有答案了 我需要更新新行 如果两者都满足 date dat and empId who 作为复合键 但如果其中之一或两者不同 则插入 sql INSERT INTO history SET endtimestamp now
  • 基本表创建 fpdf

    我找不到使用 fpdf 制作表格并从 mysql 数据库获取数据的合适教程 我只是想知道如何创建一个 我在网上尝试示例时遇到了很多错误 例如 我有 名字 中间名 姓氏 年龄 和 电子邮件 列 如何使用 fpdf 创建表格并回显数据库中的条目
  • Laravel Sum 列数据库 Eloquent

    尝试获取我的一个表中 int 字段的总和应该非常容易 不幸的是 事实并非如此 因为无论我使用 Laravel MySQL 还是 Excel 我都会得到不同的结果 Laravel 5 4 给了我20506 Table sum field na
  • Laravel Group By 和 Order By 不起作用

    我尝试制作一个Laravel 5 8项目 项目中的数据是这样的 id purch name prcvalue 1 10234 Nabila 100 2 10234 Nadeera 450 3 10234 Nabila 540 4 10234
  • 如何在Sequelize中从主模型同一级别的包含模型返回结果?

    这是我在项目中完成的代码和结果 我想获得包含模型的结果与主模型相同的结果 下面的代码是我所做的 序列化查询 User findAll include model Position attributes POSITION NAME then
  • 在 MySQL 数据库上使用版本控制 (Git)

    我是一名 WordPress 设计师 开发人员 越来越多地使用版本控制 特别是 Git 尽管我确实在某些项目中使用 SVN 我目前正在使用 Beanstalk 作为我的远程仓库 将所有 WordPress 文件添加到我的存储库中是没有问题的
  • 项目链接在 Wamp 服务器上不起作用

    我正在另一台计算机上安装 Wamp 服务器来运行中型数据库和 UI 我已成功阻止 IIS 并将服务器路由到 Localhost 8080 但是每当我尝试从 localhost 主页访问我的项目时 在 www 文件中 我被重定向到页面未找到错
  • 如何使用 exec.Command 在 golang 中执行 Mysql 脚本

    您好 我正在尝试执行一个脚本以使用 Golang 将数据填充到数据库中 func executeTestScript cmd exec Command usr local mysql bin mysql h127 0 0 1 P3333 u
  • 错误代码 13,SELECT INTO OUTFILE 问题

    我试图了解使用 INTO OUTFILE 命令时不断遇到问题的原因 我总是收到这个错误 ERROR 1 HY000 Can t create write to file var www p1 txt Errcode 13 SELECT pa
  • 如何编写 bash 函数来包装另一个命令?

    我正在尝试编写一个函数包装器mysql command If my cnf存在于 pwd 中 我想自动附加 defaults file my cnf到命令 这就是我正在尝试的 function mysql if e my cnf then
  • MySQL 中非空值的计数和分组

    我需要计算按特定 ID 分组的非空 我的意思是至少包含 1 个字符的字符串 行 例如 我的数据可能如下所示 form id mapping 1 value 1 1 1 value 2 2 2 NULL 3 value 3 我想计算每个表单的
  • MySQL:空间查询查找纬度/经度点是否位于给定边界内

    我正在研究谷歌地图搜索功能 其目的是找出 地理位置 点是否位于多边形内 如下图所示 我使用带有 Spatial 扩展的 mysql 5 6 20 我知道它内置有用的几何函数 因此我可以直接从数据库查询地理编码位置 我的目的是熟悉地理空间函数
  • PHP + MySQL 队列

    我需要一个充当队列的简单表 我的 MySQL 服务器限制是我不能使用 InnoDB 表 只能使用 MyISAM 客户 工人将同时工作 他们每次都需要接受不同的工作 我的想法是执行以下操作 伪代码 job lt SELECT FROM que
  • MySQL 和 MariaDB 数据库有什么区别?

    我已经使用 XAMPP 很长时间了 很惊讶 XAMPP 已经从 MySQL 切换到了 MariaDB https www apachefriends org index html https www apachefriends org in

随机推荐

  • 银行排队模拟(队列)

    银行排队模拟程序 队列类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 五