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

news2024/12/23 12:08:54

假设存在表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()
begin
 declare i int;
 set i=1;
 while(i<=100000)do
   insert 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语句的时候释放。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2136197.html

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

相关文章

C++速通LeetCode简单第11题-对称二叉树

递归法&#xff1a; /*** Definition for a binary tree node.* struct TreeNode {* int val;* TreeNode *left;* TreeNode *right;* TreeNode() : val(0), left(nullptr), right(nullptr) {}* TreeNode(int x) : val(x), left(nullptr), right(nullptr) …

探索螺钉设计:部分螺纹与全螺纹,哪种更适合你的项目?

为什么有些螺钉有部分螺纹? 螺钉由头部、柄部和尖端组成&#xff0c;是世界上zui常用的紧固件之一。与螺栓一样&#xff0c;它们旨在将多个对象或表面连接在一起。但是&#xff0c;在比较不同类型的螺钉时&#xff0c;您可能会注意到其中一些都具有部分螺纹杆。 什么是螺柄&a…

第3篇:【系统分析师】数据库系统

基本概念 三级模式-两级映像 数据库设计 掌握数据库设计的步骤顺序&#xff0c;以及各个阶段的产出物。在逻辑结构设计中做范式处理 数据库模型 E-R模型 关系模型 关系代数&#xff08;sql语言&#xff09; 规范化 函数依赖&#xff0c;键与约束&#xff0c;模式分解 范式 …

国家网信办就人工智能生成合成内容标识征求意见

国家互联网信息办公室发布《人工智能生成合成内容标识办法&#xff08;征求意见稿&#xff09;》&#xff0c;该办法根据《中华人民共和国网络安全法》、《互联网信息服务算法推荐管理规定》、《互联网信息服务深度合成管理规定》、《生成式人工智能服务管理暂行办法》等法律法…

【案例71】配置https之后 IE打不开登陆页面 Uclient没有问题

问题现象 配置https之后 IE打不开登陆页面 Uclient没有问题。 jvm控制台 显示如下 basic: 已调整小应用程序大小且已将其添加到父容器中 basic: PERF: AppletExecutionRunnable - applet.init() BEGIN ; jvmLaunch dt 170755 us, pluginInit dt 722531 us, TotalTime: 89328…

教你制作动态可以点击的PDF样本图册

普通的PDF文档虽然方便&#xff0c;但静态的页面往往难以满足一些展示和功能性的需求。今天&#xff0c;就让我来带你了解一下如何制作动态可点击的PDF样本图册&#xff0c;让我们的PDF文档焕发新的活力&#xff01; 首先&#xff0c;我们需要明确制作动态可点击PDF的目的是什…

【MPC】无人机模型预测控制复现Data-Driven MPC for Quadrotors项目(Part 1)

无人机模型预测控制复现Data-Driven MPC for Quadrotors项目 参考链接背景和问题方法与贡献实验结果安装ROS创建工作空间下载RotorS仿真器源码和依赖创建Python虚拟环境下载data_driven_mpc仓库代码下载并配置ACADO求解器下载并配置ACADO求解器的Python接口下载并配置rpg_quadr…

时间安全精细化管理平台存在未授权访问漏洞

漏洞描述 登录--时间&amp;安全精细化管理平台存在未授权访问漏洞导致与员工信息泄露 FOFA&#xff1a; body"登录--时间&amp;安全精细化管理平台" POC IP/acc/_checkinoutlog_/

一分钟教你 全平台隔空投送文件 LoaclSend保姆级教程

主要内容 什么是LoaclSend 详细步骤 1.下载LoaclSend 2.使用MoleSDN 异地访问 3.一切就绪&#xff0c;打开LocalSend 发送文件 什么是LoaclSend 一款开源的文件传输工具&#xff0c;旨在提供简单、安全、快速的本地文件传输。 LocalSend可以免费使用且无需注册登录&…

element-plus表单使用show-overflow-tooltip,避免占满屏幕,需要设置宽度

在表单中&#xff0c;<el-table-clumn>中添加show-overflow-tooltip&#xff0c;可以实现表格内容过多的问题。 属性官方解释&#xff1a;是否隐藏额外内容并在单元格悬停时使用 Tooltip 显示它们。 出现的问题&#xff1a; 使用了该属性之后&#xff0c;弹出的详细内…

设置使用阿里云服务器DNS

由于云服务器是从腾讯云迁移到阿里云&#xff0c;然后使用ssl验证时一直无法使用dns验证&#xff0c;也无法创建三级域名&#xff0c;原来需要把阿里云服务器改成阿里云的dns使用 如果使用其他服务器DNS会下面会显示当前DNS服务器&#xff0c;

Linux进阶命令-sortwc

作者介绍&#xff1a;简历上没有一个精通的运维工程师。希望大家多多关注作者&#xff0c;下面的思维导图也是预计更新的内容和当前进度(不定时更新)。 经过上一章Linux日志的讲解&#xff0c;我们对Linux系统自带的日志服务已经有了一些了解。我们接下来将讲解一些进阶命令&am…

Leetcode Hot 100刷题记录 -Day13(除自身以外数组的乘积)

除自身以外数组的乘积 问题描述&#xff1a; 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不…

[云服务器9]使用django搭建论坛网站?

准备 首先&#xff0c;我们打开雨云官网。 然后我们注册一个账号&#xff0c;注册并登录好后&#xff0c;我们找到主面版的云服务器&#xff0c;然后点击购买云服务器。 配置我们2h2g就足够了&#xff0c;因为我们的流量不是那么大……操作系统推荐选Ubuntu&#xff0c;预装选…

【C++二分查找】2560. 打家劫舍 IV

本文涉及的基础知识点 C二分查找 LeetCode2560. 打家劫舍 IV 沿街有一排连续的房屋。每间房屋内都藏有一定的现金。现在有一位小偷计划从这些房屋中窃取现金。 由于相邻的房屋装有相互连通的防盗系统&#xff0c;所以小偷 不会窃取相邻的房屋 。 小偷的 窃取能力 定义为他在…

荣耀时刻|Anzo Capital 闪耀2024国际金融产业博览会

【2024年9月5日-6日&#xff0c;中国香港】由数汇金融和汇友网主办的2024年国际金融产业博览会香港峰会在香港康得思酒店举行&#xff0c;Anzo Capital 昂首资本作为顶级赞助商和重磅受邀嘉宾出席了本次展会。 此次展会汇聚了众多行业领军企业、知名专家以及投资机构&#xff…

【趣学Python算法100例】抓交通肇事犯

问题描述 一辆卡车违反交通规则&#xff0c;撞人后逃跑。现场有三人目击该事件&#xff0c;但都没有记住车号&#xff0c;只记下了车号的一些特征。甲说&#xff1a;牌照的前两位数字是相同的&#xff1b;乙说&#xff1a;牌照的后两位数字是相同的&#xff0c;但与前两位不同…

Linux - make/Makefile工具的基础使用

文章目录 一、介绍二、工作原理三、使用1、make的使用2、make的常用选项3、Makefile文件 四、总结 一、介绍 make工具和 Makefile 文件是 Linux下非常重要的自动化构建工具&#xff0c; Makefile定义了项目的编译规则&#xff0c;指示make如何编译和链接源代码以生成可执行文件…

[wowoza]使用rtsp协议向wowza推流方法

1、测试前要关闭电脑防火墙 2、测试前要关闭推流验证功能 3、3、关闭回放验证功能 上面设置修改后&#xff0c;要点击restart重启 4、查看服务器ip、端口号、application test player可以预览推流的音视频 有时候需要缓存 url里面注意没有空格

牛客练习赛128(上)

Cidoai的幂次序列 题目描述 登录—专业IT笔试面试备考平台_牛客网 运行代码 #include <bits/stdc.h> using namespace std; signed main(){long long n,k;cin>>n>>k;cout<<2<<\n;cout<<n-1<< <<1<<\n;return 0; } 代…