当前位置: 首页 > news >正文

64 mysql 的 表锁

前言

我们这里来说的就是 我们在 mysql 这边常见的 几种锁

行共享锁, 行排他锁, 表意向共享锁, 表意向排他锁, 表共享锁, 表排他锁

我们前面了解了行共享锁, 行排他锁, 表意向共享锁, 表意向排他锁 等等相关

我们这里 来看一下 表共享锁, 表排他锁 的获取, 以及 和 其他表级别锁的冲突的处理

 

需要设置 auto_commit 为 0, 否则不会走 表锁 的相关业务流程

 

 

表排他锁

我们这里调试 sql 如下 这里会先获取 t_user_02 的表排他锁, 然后再释放掉 

begin;
lock tables t_user_02 write;
unlock tables;
commit;

 

我们这里重点关注 “lock tables t_user_02 write;” 的执行流程 

3dd7cc93a2ed6b936a3aad7a03e29ed0.png

 

表锁 mysql层 到 innodb引擎层 的适配是这里的 handler.cc 中进行适配的 

到下图断点这里是 innodb 的处理, 验证了 lock 命令, autocommit 为 false 以及一些其他的条件, 然后 row_lock_table_for_mysql 是整体的获取表锁的业务流程, 诸如 获取到锁之后继续往下走, 没有获取到锁之后 wait, 重试 等等

991523dd4087fce369fd793bffd8c10e.png

 

这里就是获取表锁的宏观流程了, 如果获取到了 则直接返回 

如果没有获取到, 则挂起当前线程, 等待唤醒, 唤醒之后 进行重试

835201ec355509839d256575ac25d000.png

 

获取表锁的具体实现如下, 和之前的获取 表意向共享锁, 表意向排他锁 的情况类似

我们这里重点看一下 表级别锁的兼容机制, 这是影响到能否获取到锁的关键 

47703252643c170e1493d4a555d6648d.png

 

我们这里将问题简单化, 暂时不考虑 matrix 中的 自增长锁 的处理

表意向锁 和 表意向锁 之间是相互兼容的 

表意向锁 和 表锁 之间兼容如下, 表意向共享锁 和 表共享锁 兼容, 其他的三种情况互不兼容 

表锁 和 表锁 之间的兼容如下, 表共享锁 和 表共享锁 兼容, 其他的三种情况互不兼容 

 

对于我们这里 获取表排他锁的场景下面, 只有无锁状态, 我们可以获取成功, 但凡有 其他事务持有 表意向共享/排他锁, 表共享/排他锁 当前事务的获取 表排他锁 都会失败

对于获取 表共享锁 的场景下面, 只有无锁状态, 其他事务获取了表意向共享锁 或者 表共享锁 的情况下面, 我们可以获取锁成功, 但凡有其他事务持有 表意向排他锁, 表排他锁, 当前事务的获取 表共享锁 都会失败

44e9b0931ddcddaa861109cf0113a242.png

 

 

表共享锁

我们这里调试 sql 如下 这里会先获取 t_user_02 的表共享锁, 然后再释放掉 

begin;
lock tables t_user_02 read;
unlock tables;
commit;

 

这里的获取 表共享锁 的流程和前面 获取 表排他锁 的流程一样, 只是 锁的兼容有一些 差异

c373523cd49b71ea895c466b6bb8003e.png

 

我们这里将问题简单化, 暂时不考虑 matrix 中的 自增长锁 的处理

表意向锁 和 表意向锁 之间是相互兼容的 

表意向锁 和 表锁 之间兼容如下, 表意向共享锁 和 表共享锁 兼容, 其他的三种情况互不兼容 

表锁 和 表锁 之间的兼容如下, 表共享锁 和 表共享锁 兼容, 其他的三种情况互不兼容 

 

对于我们这里 获取表共享锁的场景下面, 只有无锁状态, 其他事务获取了表意向共享锁 或者 表共享锁 的情况下面, 我们可以获取锁成功, 但凡有其他事务持有 表意向排他锁, 表排他锁, 当前事务的获取 表共享锁 都会失败

对于 获取表排他锁的场景下面, 只有无锁状态, 我们可以获取成功, 但凡有 其他事务持有 表意向共享/排他锁, 表共享/排他锁 当前事务的获取 表排他锁 都会失败

36927d9bb4d74aa48af28c8795911351.png

 

 

表排他锁阻塞的 N 种方式

表意向排他锁 和 表排他锁 的阻塞方式基本上是一样的, 这里不多赘述 

假设我们这里尝试模拟 各种阻塞的方式, 事务1先进行执行, 然后事务2尝试获取表排他锁, 产生阻塞 

但是这些阻塞 是还没有到获取表锁 之前的目标表的 MDL元数据锁的阻塞 

事务2 这边执行固定的 sql 语句如下 

begin;
lock tables t_user_02 write;
unlock tables;
commit;

 

事务1获取 表意向共享锁 导致 事务2 获取MDL元数据锁 阻塞 

begin;
select * from t_user_02 where id = '1' lock in share mode;
-- sleep 10min
commit;

 

事务1获取 表意向排他锁 导致 事务2获取MDL元数据锁 阻塞

begin;
select * from t_user_02 where id = '1' for update;
-- sleep 10min
commit;

 

事务1获取 表共享锁锁 导致 事务2获取MDL元数据锁 阻塞

begin;
lock tables t_user_02 read;
-- sleep 10min
unlock tables;
commit;

 

事务1获取 表排他锁锁 导致 事务2获取MDL元数据锁 阻塞

begin;
lock tables t_user_02 write;
-- sleep 10min
unlock tables;
commit;

 

 

表共享锁阻塞的 N 种方式

假设我们这里尝试模拟 各种阻塞的方式, 事务1先进行执行, 然后事务2尝试获取表共享锁, 产生阻塞 

但是这些阻塞 是还没有到获取表锁 之前的目标表的 MDL 元数据锁的阻塞 

事务2 这边执行固定的 sql 语句如下 

begin;
lock tables t_user_02 read;
unlock tables;
commit;

 

事务1获取 表意向排他锁 导致 事务2获取MDL元数据锁 阻塞

begin;
select * from t_user_02 where id = '1' for update;
-- sleep 10min
commit;

 

事务1获取 表排他锁锁 导致 事务2获取MDL元数据锁 阻塞

begin;
lock tables t_user_02 write;
-- sleep 10min
unlock tables;
commit;

 

 

表锁的 阻塞 和 唤醒

假设我们这边 事务1 执行 sql 如下 

begin;
select * from t_user_02 where id = '2' for update;
-- sleep 10min
commit;

 

事务2 执行 sql 如下, 然后到 “select * from t_user_02 where id = '2' for update;

” 的时候, 事务会阻塞, 然后 之后手动 commit 事务1, 可以看到 唤醒的流程

begin;
select * from t_user_02 where id = '2' for update;
-- sleep 10min
commit;

 

这个就是通过线程的相关 api 进行 wait 和 notify 了 

wait 这边这边主要是基于 pthread_cond_wait 来进行线程的挂起处理 

6880273094db22086a66e2c2a30a8df6.png

 

手动 commit 事务1, thr 是目标锁 等待队列中取出的一个待唤醒的线程

然后设置会 设置 pthread_cond_wait 中的等待的条件, 以达到唤醒目标线程的效果 

8ab89684cf73ec15848f3671c0d71da1.png

 

来到目标线程这边, 目标线程 被唤醒了, 然后继续走后面的流程 

dab78cd54fd806ca4eaf77fb7f57f7ef.png

 

 

行锁, 表锁, 元数据锁 的查看

行锁的阻塞信息, 可以再 INNODB_LOCKS, INNODB_LOCK_WAITS 中查看 

select * from information_schema.INNODB_LOCKS;
select * from information_schema.INNODB_LOCK_WAITS;

 

构造一个 事务1 获取 id 为 2 的记录的行共享锁, 事务2 获取 id 为 2 的记录的行排他锁, 造成的阻塞 

从这里可以看到 两个事务尝试获取 t_user_02 表的 第3条 记录, 一个获取行共享锁, 一个获取行排他锁

结合等待信息来看, 可以看出的是 获取 行排他锁 的事务在等待 持有 行共享锁 的事务

68a23ca8c9aa9117db7efcb0fbc5fd8e.png

7e73270a119c30950b6ad82424c73ac8.png

 

show processlist 可以看到等待的线程, 以及阻塞的 sql 

工作线程一般是靠后面的线程, 可以推断出 持有锁的线程是 30号, 阻塞的是 31号 线程

026fa9076b9d6f189ec9274d5c1791aa.png

 

 

表锁的阻塞信息, 可以通过如下命令来查看

show open tables where in_use > 0; 

 

执行结果如下, 可以推断的是 t_user_02 的表锁被一个事务持有, 具体的是读锁还是写锁分辨不出来, 只能通过 实际的业务锁获取来判断

如果业务这边获取的是读锁, 则表示持有的是写锁, 如果业务这边获取的是写锁, 则判断不了持有的是读锁还是写锁 

df005f4c21f23a2852af5ca9d52c841b.png

 

show processlist 可以看到等待的线程, 以及阻塞的 sql 

工作线程一般是靠后面的线程, 可以推断出 持有锁的线程是 30号, 阻塞的是 31号 线程

10df0414a3fde2ee3b3d1beb008f52fd.png

 

 

元数据锁 这边一般只有通过 show processlist 中可以看出了 或者 mysql 服务器的堆栈信息

比如如上 表锁的例子

元数据锁在大多数的命令都会获取, 但是生命周期不太一样 

比如 “lock tables t_user_02 read/write;” 类型的指令, 是先获取 表的元数据锁, 然后再执行业务处理, 再释放 表的元数据锁

比如 “select * from t_user_02 where id = '2' for update;” 类型的指令, 是先获取 表的元数据锁, 然后释放 表的元数据锁, 最后再执行业务处理 

因此 构造元数据锁阻塞的方式可以由 事务1 获取表锁, 事务2 获取表锁, 或者行锁都会阻塞, 事务2 阻塞是阻塞在获取 表元数据锁 的地方

8cc70894e23a49344b58732ef165e4da.png

 

 

 

 

 

相关文章:

64 mysql 的 表锁

前言 我们这里来说的就是 我们在 mysql 这边常见的 几种锁 行共享锁, 行排他锁, 表意向共享锁, 表意向排他锁, 表共享锁, 表排他锁 我们前面了解了行共享锁, 行排他锁, 表意向共享锁, 表意向排他锁 等等相关 我们这里 来看一下 表共享锁, 表排他锁 的获取, 以及 和 其他表级…...

【计网不挂科】计算机网络期末考试——【选择题&填空题&判断题&简述题】题库(1)

前言 大家好吖,欢迎来到 YY 滴计算机网络 系列 ,热烈欢迎! 本章主要内容面向接触过C的老铁 本博客主要内容,收纳了一部门基本的计算机网络题目,供yy应对期中考试复习。大家可以参考 欢迎订阅 YY滴其他专栏!…...

ajax关于axios库的运用小案例

AJAX案例 图书管理 四大功能: 展示图书删除图书编辑图书信息新增图书 步骤 1.bootstrap弹窗来实现新增和编辑图书时出现的弹窗 有两种方案: a.可以用自带的属性来进行弹窗的显示和隐藏 b.可以通过JS进行控制,此操作可以进行自定义&am…...

微搭低代码入门01变量

目录 1 变量的定义2 变量的赋值3 变量的类型4 算术运算符5 字符串的连接6 模板字符串7 检查变量的类型8 解构赋值8.1 数组的解构赋值8.2 对象的解构赋值 9 类型转换9.1 转换为字符串9.2 转换为数字9.3 转换为布尔值 总结 好些零基础的同学,在使用低代码的时候&#…...

盘点2024年10款视频剪辑,哪款值得pick!!

在这个短视频盛行的时代,如何让我们的故事更生动有趣呢?那就要对短视频进行修饰了。这就需要借助视频剪辑工具:而一款好的工具不仅仅是视频的“美颜”,更是创意的灵魂所在!想象一下,运用一款功能齐全的剪辑…...

苹果手机照片批量删除:一键清理,释放空间

在数字化时代,iPhone不仅是我们沟通的桥梁,也是记录生活的重要工具。然而,随着时间的积累,手机中的照片数量不断增加,不仅占用大量存储空间,也让设备变得缓慢。苹果手机照片批量删除成为了一个普遍的需求。…...

《AI 大模型:重塑软件开发新生态》

《AI 大模型:重塑软件开发新生态》 一、AI 大模型引领软件开发新潮流二、AI 大模型在软件开发中的优势(一)提高开发效率(二)减少错误与提升质量(三)激发创新与拓展功能 三、AI 大模型在软件开发…...

uniapp(API-Promise 化)

一、异步的方法,如果不传入 success、fail、complete 等 callback 参数,将以 Promise 返回数据异步的方法,且有返回对象,如果希望获取返回对象,必须至少传入一项 success、fail、complete 等 callback 参数&#xff0c…...

【考研数学 - 数二题型】考研数学必吃榜(数二)

数学二 suhan, 2024.10 文章目录 数学二一、函数❗1.极限1.1求常见极限1.2求数列极限1.2.1 n项和数列极限1.2.2 n项连乘数列极限1.2.3 递推关系定义的数列极限 1.3确定极限式中的参数1.4无穷小量阶的比较 2.连续2.1判断是否连续,不连续则判断间断点类型2.2证明题 二…...

Redis生产问题(缓存穿透、击穿、雪崩)——针对实习面试

目录 Redis生产问题什么是缓存穿透?如何解决缓存穿透?什么是缓存击穿?如何解决缓存击穿?缓存穿透和缓存击穿有什么区别?什么是缓存雪崩?如何解决缓存雪崩? Redis生产问题 什么是缓存穿透&#x…...

android openGL中模板测试、深度测试功能的先后顺序

目录 一、顺序 二、模板测试 1、概念 2、工作原理 3、关键函数 三、深度测试 1、概念 2、工作原理 3、关键函数 三、模板测试和深度测试的先后顺序 一、顺序 在Android OpenGL中,模板测试(Stencil Testing)是在深度测试&#xff0…...

CCF PTA 编程培训师资认证2021年7月真题- C++兑换礼品

【题目描述】 小零和小壹是两个爱玩游戏的小孩,他俩平时最擅长的是解谜游戏,可今天 遇到了一个有点难的算法问题,希望能得到你的帮助。 他们面对的是一个电子装置,正面有 n 个排成一列的按钮,按钮上贴着编号 1~n 号的…...

火山引擎云服务docker 安装

安装 Docker 登录云服务器。 执行以下命令,添加 yum 源。 yum update -y yum install epel-release -y yum clean all yum list依次执行以下命令,添加Docker CE镜像源。更多操作请参考Docker CE镜像。 # 安装必要的一些系统工具 sudo yum install -y yu…...

【taro react】 ---- 常用自定义 React Hooks 的实现【六】之类渐入动画效果的轮播

1. 效果 2. 场景 css 效果实现:可以看到效果图中就是一个图片从小到大的切换动画效果,这个效果很简单,使用 css 的 transform 的 scale 来实现图片的从小到大的效果,切换就更加简单了,不管是 opacity 还是 visibility 都可以实现图片的隐藏和显示的切换。React.Children.m…...

基础算法练习--滑动窗口(已完结)

算法介绍 滑动窗口算法来自tcp协议的一种特性,它的高效使得其也变成了算法题的一种重要考点.滑动窗口的实现实际上也是通过两个指针前后遍历集合实现,但是因为它有固定的解题格式,我将其单独做成一个篇章. 滑动窗口的解题格式: 首先,定义两个指针left和right,与双指针不同的…...

深度学习经典模型之ZFNet

1 ZFNet 1.1 模型介绍 ​ ZFNet是由 M a t t h e w Matthew Matthew D . Z e i l e r D. Zeiler D.Zeiler和 R o b Rob Rob F e r g u s Fergus Fergus在AlexNet基础上提出的大型卷积网络,在2013年ILSVRC图像分类竞赛中以11.19%的错误率获得冠军(实际…...

Linux系统-ubuntu系统安装

作者介绍:简历上没有一个精通的运维工程师。希望大家多多关注作者,下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 这是Linux进阶部分的最后一大章。讲完这一章以后,我们Linux进阶部分讲完以后,我们的Linux操作部分就…...

2-Ubuntu/Windows系统启动盘制作

学习目标: 掌握使用Win32DiskImager、Rufus等工具制作系统启动盘的基本步骤。独立将ISO镜像文件写入USB闪存驱动器,确保在需要时顺利安装或修复系统。通过学习如何选择正确的源文件和目标驱动器,理解启动盘的使用场景和注意事项,…...

你使用过哪些MySQL中复杂且使用不频繁的函数?

在MySQL中,除了常用的SELECT、INSERT、UPDATE等基本操作外,还有许多复杂且功能强大的函数,它们能够处理各种复杂的数据处理需求。这些函数虽然在日常开发中可能不常使用,但在特定场景下却能够发挥巨大的作用。下面,我将…...

Redis-07 Redis哨兵

操作实现 此处应该6台虚拟机,其中3台是哨兵,但因为内存限制没有那么多 1.将sentinel文件拷贝到/myredis目录下 2.sentinel.conf文件重要参数 新建配置文件sentinel26379.conf sentinel26380.conf sentinel26381.conf bind 0.0.0.0 daemonize yes pr…...

idea大量爆红问题解决

问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

(二)TensorRT-LLM | 模型导出(v0.20.0rc3)

0. 概述 上一节 对安装和使用有个基本介绍。根据这个 issue 的描述,后续 TensorRT-LLM 团队可能更专注于更新和维护 pytorch backend。但 tensorrt backend 作为先前一直开发的工作,其中包含了大量可以学习的地方。本文主要看看它导出模型的部分&#x…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

涂鸦T5AI手搓语音、emoji、otto机器人从入门到实战

“🤖手搓TuyaAI语音指令 😍秒变表情包大师,让萌系Otto机器人🔥玩出智能新花样!开整!” 🤖 Otto机器人 → 直接点明主体 手搓TuyaAI语音 → 强调 自主编程/自定义 语音控制(TuyaAI…...

华为云Flexus+DeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建

华为云FlexusDeepSeek征文|DeepSeek-V3/R1 商用服务开通全流程与本地部署搭建 前言 如今大模型其性能出色,华为云 ModelArts Studio_MaaS大模型即服务平台华为云内置了大模型,能助力我们轻松驾驭 DeepSeek-V3/R1,本文中将分享如何…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

USB Over IP专用硬件的5个特点

USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...

【Java学习笔记】BigInteger 和 BigDecimal 类

BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...