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

MySQL查询执行(四):查一行也很慢

假设存在表t,这个表有两个字段id和c,并且我在里面插入了10万行记录。

-- 创建表t
CREATE TABLE `t` (`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB;-- 通过存储过程向t写入10w行数据
delimiter ;;
create procedure idata()
begindeclare i int;set i=1;while(i<=100000)doinsert into t values(i,i);set i=i+1;end while;
end;;
delimiter ;-- 插入数据
call idata();

查询长时间不返回


查询长时间不返回的原因:被其他线程堵住了。

在表t执行下面的SQL语句:

select * from t where id = 1;

查询结果长时间不返回。

一般碰到这种情况的话, 大概率是表t被锁住了。 接下来分析原因的时候, 一般都是首先执行一下show processlist命令, 看看当前语句处于什么状态。

然后我们再针对每种状态, 去分析它们产生的原因、 如何复现, 以及如何处理。

场景一:等MDL锁

如图所示, 就是使用show processlist命令查看Waiting for table metadata lock的示意图。

出现这个状态表示的是, 现在有一个线程正在表t上请求或者持有MDL写锁, 把select语句堵住了。

在MySQL 5.7版本下复现这个场景, 如图所示, 我给出了简单的复现步骤。

session A 通过lock table命令持有表t的MDL写锁, 而session B的查询需要获取MDL读锁。 所以, session B进入等待状态。

这类问题的处理方式, 就是找到谁持有MDL写锁, 然后把它kill掉。

问:如何找到是谁持有MDL写锁呢?

方式一:如果session A在加表锁后,接着执行了别的语句,那么便可通过执行show processlist命令找到造成阻塞的process id。

方式二:如果如果session A在加表锁后,没有执行任何命令,即Command列是“Sleep”。此时需要通过查询sys.schema_table_lock_waits这张表,找出造成阻塞的process id。(MySQL启动时需要设置performance_schema=on,MySQL5.5默认是关闭此功能的,若要开启,需手动在配置文件里添加,从MySQL5.6开始,默认打开此功能)

在上述场景下,另启一个session C,然后执行:

select blocking_pid from sys.schema_table_lock_waits;

执行结果:

最后,在找到造成阻塞的process id后,把这个连接用kill命令断开即可。

场景二:等flush

MySQL里面对表做flush操作的用法, 一般有以下两个:

-- flush指定table
flush tables t with read lock;--flush全部table 
flush tables with read lock;

这两个flush语句, 如果指定表t的话, 代表的是只关闭表t; 如果没有指定具体的表名, 则表示关闭MySQL里所有打开的表。

正常情况下,这两个语句执行起来都很快, 除非它们也被别的线程堵住了。

所以, 出现Waiting for table flush状态的可能情况是: 有一个flush tables命令被别的语句堵住了, 然后它又堵住了我们的select语句。

注:flush table的作用,关闭表,并清空查询缓存。

现在, 我们一起来复现一下这种情况, 复现步骤如图所示:

在session A中, 我故意每行都调用一次sleep(1), 这样这个语句默认要执行10万秒, 在这期间表t一直是被session A“打开”着。 然后, session B的flush tables t命令再要去关闭表t, 就需要等session A的查询结束。 这样, session C要再次查询的话, 就会被flush 命令堵住了。

这个复现步骤的show processlist结果:

看到这个show processlist的结果, 肯定就知道应该怎么做了。

场景三:等行锁

经过了表级锁的考验, 我们的select 语句终于来到引擎里了。

select * from t where id=1 lock in share mode;

由于访问id=1这个记录时要加读锁, 如果这时候已经有一个事务在这行记录上持有一个写锁, 我们的select语句就会被堵住。

复现步骤和现场如下:

显然, session A启动了事务, 占有写锁, 还不提交, 是导致session B被堵住的原因。

问:等行锁的场景下,怎么查出是谁占着这个写锁呢?

答:如果是MySQL5.7及以上版本,可以通过sys.innodb_lock_waits 表查到。

查询方法:

select * from t sys.innodb_lock_waits where locked_table=`'test'.'t'`\G

执行结果:

可以看到, 这个信息很全, 4号线程是造成堵塞的罪魁祸首。 而干掉这个罪魁祸首的方式, 就是KILL 4。

查询慢


经过了重重封“锁”, 我们再来看看一些查询慢的例子。

先来看一条你一定知道原因的SQL语句:

select * from t where c = 50000 limit 1;

由于字段c上没有索引, 这个语句只能走id主键顺序扫描, 因此需要扫描5万行。

接下来, 我们再看一个只扫描一行, 但是执行很慢的语句。

select * from t where id = 1;

慢查询结果:

虽然扫描行数是1, 但执行时间却长达800毫秒。是不是有点奇怪呢, 这些时间都花在哪里了?

如果我把这个slow log的截图再往下拉一点, 你可以看到下一个语句, select * from t where id=1 lock in share mode, 执行时扫描行数也是1行, 执行时间是0.2毫秒。

看上去是不是更奇怪了? 按理说lock in share mode还要加锁, 时间应该更长才对啊。

场景复现:

session A先用start transaction with consistent snapshot(该命令启动事务时就创建了一致性视图)命令启动了一个事务, 之后session B才开始执行update 语句。session B更新完100万次, 生成了100万个回滚日志(undo log)。

session A在执行select * from t where id=1时,需要判断当前记录的可见性,由于session B执行了100万次,所以session A需要判断100万次,这也就是为什么select * from t where id=1语句执行的比较慢。

session A在执行select * from t where id=1 lock in share mode时,直接读最新记录即可,无需判断记录的可见性,所以执行的比较快。

上述两个语句的执行输出结果:

 假设有如下表结构:

CREATE TABLE `t`(`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,`d` int(11) DEFAULT NULL,PRIMARY KEY (`id`),KEY c (`c`)
) ENGINE=InnoDB;insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25);

小结:思考题


思考:如果执行如下语句,语句序列是怎么加锁的?锁又是什么时候释放的?

begin;
select * from t where c = 5 for update;
commit;

 这个语句会命中d=5的这一行, 对应的主键id=5, 因此在select 语句执行完成后, id=5这一行会加一个写锁, 而且由于两阶段锁协议, 这个写锁会在执行commit语句的时候释放。

相关文章:

MySQL查询执行(四):查一行也很慢

假设存在表t&#xff0c;这个表有两个字段id和c&#xff0c;并且我在里面插入了10万行记录。 -- 创建表t CREATE TABLE t (id int(11) NOT NULL,c int(11) DEFAULT NULL,PRIMARY KEY (id) ) ENGINEInnoDB;-- 通过存储过程向t写入10w行数据 delimiter ;; create procedure idat…...

【Obsidian】当笔记接入AI,Copilot插件推荐

当笔记接入AI&#xff0c;Copilot插件推荐 自己的知识库笔记如果增加AI功能会怎样&#xff1f;AI的回答完全基于你自己的知识库余料&#xff0c;是不是很有趣。在插件库中有Copilot插件这款插件&#xff0c;可以实现这个梦想。 一、什么是Copilot&#xff1f; 我们知道githu…...

Spring Cloud集成Gateaway

Spring Cloud Gateway 是一个基于 Spring 生态的网关框架&#xff0c;用于构建微服务架构中的API网关。它可以对请求进行路由、过滤、限流等操作&#xff0c;是Spring Cloud微服务体系中常用的组件之一。下面介绍 Spring Cloud Gateway 的核心概念、应用场景以及简单的示例。 …...

如何准备技术面试?

大家好&#xff0c;我是老三&#xff0c;好久没更新了&#xff0c;翻出之前的一篇旧稿&#xff0c;是一篇总纲性质的文章——如何准备一场技术面试。这篇文章原本的开头是写给金三银四的&#xff0c;转眼就“金九银十”了&#xff0c;每一年都是最差的一年&#xff0c;又是未来…...

Kafka原理剖析之「Topic创建」

一、前言 Kafka提供了高性能的读写&#xff0c;而这些读写操作均是操作在Topic上的&#xff0c;Topic的创建就尤为关键&#xff0c;其中涉及分区分配策略、状态流转等&#xff0c;而Topic的新建语句非常简单 bash kafka-topics.sh \ --bootstrap-server localhost:9092 \ // …...

Java 高级学习路线概要~

前言&#xff1a;恭喜你已经掌握了 Java 的基础知识&#xff01;现在&#xff0c;让我们踏上 Java 高级学习之旅&#xff0c;探索更强大的编程技巧和技术。学习前记得不要忘了巩固和加强基础的学习哦&#xff0c;高级学习也是建立在基础的学习之上。 1. 集合框架进阶 Map 接口…...

浏览器插件快速开启/关闭IDM接管下载

假设你已经为浏览器安装了IDM扩展&#xff0c;那么按下图的点击顺序&#xff0c;可以快速开启或关闭IDM的下载接管&#xff0c;而不必在IDM软件的设置->选项中&#xff0c;临时作调整。...

初识c++:入门基础

打字不易&#xff0c;留个赞再走吧~~ 目录 一.第一个c程序二.命名空间 namespace三.C输⼊&输出四.缺省参数 C兼容C语⾔绝⼤多数的语法&#xff0c;所以C语⾔实现的hello world依旧可以运⾏&#xff0c;C中需要把定义⽂件 代码后缀改为.cpp 一.第一个c程序 做好准备我们来写…...

Java Exception 异常相关总结

1.简介 在Java中&#xff0c;当代码运行有问题时会抛出异常&#xff0c;主要分为两类&#xff1a; 1.可以通过try...catch来捕获解决的&#xff0c;不影响后续执行的RuntimeException。 2.不可以通过代码解决的Exception。 为了提高代码的健壮性&#xff0c;我们会选择去捕…...

HighCharts图表自动化简介

什么是分析数据? 在任何应用程序中捕获并以图形或图表形式显示的分析数据是任何产品或系统的关键部分,因为它提供了对实时数据的洞察。 验证此类分析数据非常重要,因为不准确的数据可能会在报告中产生问题,并可能影响应用程序/系统的其他相关领域。 什么是HighChart? …...

使用LDAP登录GitLab

使用LDAP登录GitLab gitlab.rb 配置如下 gitlab_rails[ldap_enabled] true #gitlab_rails[prevent_ldap_sign_in] false###! **remember to close this block with EOS below** gitlab_rails[ldap_servers] YAML.load <<-EOSmain:label: LDAPhost: 172.16.10.180port:…...

【2024】前端学习笔记5-表单标签使用

表单是网页提供的一种交互式操作手段,主要用于采集用户输入的信息。 学习笔记 1.表单框架:form标签1.1.action属性:目标指向1.2.method属性:提交方式1.3.id属性:唯一标识1.4.placeholder属性:提示文字2.input标签2.1.text类型:基本文本输入2.2.password类型:密码输入2.…...

数据结构--二叉树(C语言实现,超详细!!!)

文章目录 二叉树的概念代码实现二叉树的定义创建一棵树并初始化组装二叉树前序遍历中序遍历后序遍历计算树的结点个数求二叉树第K层的结点个数求二叉树高度查找X所在的结点查找指定节点在不在完整代码 二叉树的概念 二叉树&#xff08;Binary Tree&#xff09;是数据结构中一种…...

【将字符串变为空的编辑距离】

题目描述 求由s串变成t串的编辑距离 在s串的开头/末尾添加一个字符&#xff0c;花费p 在s串的开头/末尾添加一个s串的子串&#xff0c;花费q 每次作都是基于当前的s串 s串初始为空 分析 等价于将一个字符串变为空串的过程 第一层按照长度遍历&#xff08;如果按照下标i,j遍…...

卡特兰数的推理

卡特兰数&#xff08;Catalan number&#xff09;&#xff0c;又称卡塔兰数、明安图数&#xff0c;是组合数学中一种常出现于各种计数问题中的数列。它以比利时数学家欧仁查理卡特兰的名字命名&#xff0c;但值得注意的是&#xff0c;这一数列的首次发现可以追溯到1730年&#…...

高精度治具加工的重要性和优势

在现代工业制造中&#xff0c;高精度治具加工扮演着举足轻重的角色。它不仅关乎产品制造的精度与质量&#xff0c;还直接影响到生产效率和成本控制。因此&#xff0c;时利和将深入探讨高精度治具加工的重要性和优势&#xff0c;对于提升工业制造水平具有重要意义。 高精度治具加…...

新版IDEA提示@Autowired不建议字段注入

随着项目的复杂度的增加&#xff0c;我们通常会在一个业务类中注入其他过多的业务类。从而使当前的业务层扩充成一个大而全的功能模块。那么就容易出现一下问题 字段注入会让依赖关系变得不那么明显&#xff0c;因为你无法通过构造函数看到所有的依赖项。使用构造函数时&#…...

adb的安装和使用 以及安装Frida 16.0.10+雷电模拟器

.NET兼职社区 .NET兼职社区 .NET兼职社区 1.下载adb Windows版本&#xff1a;https://dl.google.com/android/repository/platform-tools-latest-windows.zip 2.配置adb环境变量 按键windowsr打开运行&#xff0c;输入sysdm.cpl&#xff0c;回车。 高级》环境变量》系统变量》…...

解决移动端1px 边框优化的8个方法

前言 您是否注意到 1px 边框在移动设备上有时会显得比预期的要粗&#xff1f;这种不一致源于移动屏幕的像素密度不同。 在 Web 开发中&#xff0c;我们使用 CSS 来设置页面样式。但是&#xff0c;CSS 中的 1px 并不总是转换为设备上的物理 1px。这种差异就是我们的“1px 边框…...

频带宽度固定,如何突破数据速率的瓶颈?

目录 目录 引言 信道 频带宽度 信噪比 信噪比的重要性 影响信噪比的因素 码元 码元的特点&#xff1a; 码元与比特的关系&#xff1a; 码元的作用&#xff1a; 码元的类型&#xff1a; Question 类比解释&#xff1a; 技术解释&#xff1a; 引言 在现代通信系统中…...

7.4.分块查找

一.分块查找的算法思想&#xff1a; 1.实例&#xff1a; 以上述图片的顺序表为例&#xff0c; 该顺序表的数据元素从整体来看是乱序的&#xff0c;但如果把这些数据元素分成一块一块的小区间&#xff0c; 第一个区间[0,1]索引上的数据元素都是小于等于10的&#xff0c; 第二…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

Xshell远程连接Kali(默认 | 私钥)Note版

前言:xshell远程连接&#xff0c;私钥连接和常规默认连接 任务一 开启ssh服务 service ssh status //查看ssh服务状态 service ssh start //开启ssh服务 update-rc.d ssh enable //开启自启动ssh服务 任务二 修改配置文件 vi /etc/ssh/ssh_config //第一…...

MFC内存泄露

1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

蓝桥杯 2024 15届国赛 A组 儿童节快乐

P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡&#xff0c;轻快的音乐在耳边持续回荡&#xff0c;小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下&#xff0c;六一来了。 今天是六一儿童节&#xff0c;小蓝老师为了让大家在节…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)

上一章用到了V2 的概念&#xff0c;其实 Fiori当中还有 V4&#xff0c;咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务)&#xff0c;代理中间件&#xff08;ui5-middleware-simpleproxy&#xff09;-CSDN博客…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

MFC 抛体运动模拟:常见问题解决与界面美化

在 MFC 中开发抛体运动模拟程序时,我们常遇到 轨迹残留、无效刷新、视觉单调、物理逻辑瑕疵 等问题。本文将针对这些痛点,详细解析原因并提供解决方案,同时兼顾界面美化,让模拟效果更专业、更高效。 问题一:历史轨迹与小球残影残留 现象 小球运动后,历史位置的 “残影”…...

Kafka主题运维全指南:从基础配置到故障处理

#作者&#xff1a;张桐瑞 文章目录 主题日常管理1. 修改主题分区。2. 修改主题级别参数。3. 变更副本数。4. 修改主题限速。5.主题分区迁移。6. 常见主题错误处理常见错误1&#xff1a;主题删除失败。常见错误2&#xff1a;__consumer_offsets占用太多的磁盘。 主题日常管理 …...