第十九章 为什么我只查一行的语句,也执行这么慢?

2024-01-03 16:48

本文主要是介绍第十九章 为什么我只查一行的语句,也执行这么慢?,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

第十九章 为什么我只查一行的语句,也执行这么慢?

查询长时间不返回

一条查询语句始终无返回,可能是因为什么原因导致的 ?

  • 可能在等待 MDL 锁 释放
    • 查询语句执行时申请的是 MDL 读锁,若之前有 MDL 写锁 处于申请中或正持有中,则MDL 读锁 等待
  • 可能在等待 flush 锁(在第六章讲过 flush tables with read lock 会加全局读锁)
    • 执行 flush statement 类语句可能发生锁等待,其中:
      • flush tables with read lock:会关闭所有打开的表并给所有的表在库层级添加一个全局的读锁
      • flush tables with read lock:不会被其他会话的事务阻塞。例如开启一个会话事务,更新,然后直接执行本会话 flush,此时再执行上一个会话事务的提交,提交由于 flush 进入了阻塞,在等待 flush 被unlock 之后,该事务的提交继续执行。(想要复现 flush tables with read lock 被阻塞的场景,可以让 select sleep(60) from t 来进行 —— 原理是持续不断地打开表对象)
      • flush table t with read lock:会首先获取 t 表的MDL写锁,因此它要首先等待所有打开 t 表的事务完成,然后才从表缓存中对表进行刷新,重新打开表,并获取表锁,随后将 MDL 写锁降级为 MDL 读锁。在获得表锁并进行 MDL 写锁降级后,其他连接可以读取该表,但不能更新表(DML、DDL)
      • flush table t with read lock:反而会被对应表的其他事务给阻塞到
  • 可能在等待行锁
    • 如果查询的语句加了读锁 —— lock in share mode,那当 读取的数据有写锁占用时,查询线程将被阻塞
      • lock in share mode:是要求当前读,也就是要读取最新的数据
      • 不加锁就是 一致性读,最开始读到什么,即使中间有人更新了,也读的是旧值

怎么排查查询语句很久没有反馈的情况 ? 讲一下你的步骤流程 ?

-- 查看当前库的所有线程
show processlist;
  • 此外,还可以通过 performance_schema 库 和 sys 库 来排查
show variables like '%performance_schema%';
set performance_schema = 'ON';
-- 开启此功能,会有10%的性能开销
  • 随后,执行
select * from performance_schema.setup_instruments where name='wait/lock/metadata/sql/mdl';
-- 若结果两者非YES,需设置YES,才可继续UPDATE performance_schema.setup_instruments SET ENABLED = 'YES', TIMED = 'YES' where name='wait/lock/metadata/sql/mdl';
  • 那么,当出现查询线程被阻塞时,可以在其他会话执行
SELECT * from sys.schema_table_lock_waits;
SELECT blocking_pid from sys.schema_table_lock_waits;
  • 即可查出当前持有锁的线程

Untitled

  • 建议销毁线程时,执行 kill X 而非 kill query X
  • 因为当线程正在执行的语句非查询语句时,后者是无效的方法

数据量极少但查询很慢

什么情况下,数据量极少,但查询却很慢呢 ?

  • 热点更新语句,其在 MVCC 控制下,当前事务与最新数据版本间的回滚段过长时,查询会很慢
  • 一般直接加读锁(会进行当前读)进行验证当前数据与事务一致性视图下的数据差异
  • 例如下面这个语句:
select * from t where id=1select * from t where id=1 lock in share mode

Untitled

Untitled

这篇关于第十九章 为什么我只查一行的语句,也执行这么慢?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/566389

相关文章

maven 编译构建可以执行的jar包

💝💝💝欢迎莅临我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。 推荐:「stormsha的主页」👈,「stormsha的知识库」👈持续学习,不断总结,共同进步,为了踏实,做好当下事儿~ 专栏导航 Python系列: Python面试题合集,剑指大厂Git系列: Git操作技巧GO

jenkins 插件执行shell命令时,提示“Command not found”处理方法

首先提示找不到“Command not found,可能我们第一反应是查看目标机器是否已支持该命令,不过如果相信能找到这里来的朋友估计遇到的跟我一样,其实目标机器是没有问题的通过一些远程工具执行shell命令是可以执行。奇怪的就是通过jenkinsSSH插件无法执行,经一番折腾各种搜索发现是jenkins没有加载/etc/profile导致。 【解决办法】: 需要在jenkins调用shell脚

Lua 脚本在 Redis 中执行时的原子性以及与redis的事务的区别

在 Redis 中,Lua 脚本具有原子性是因为 Redis 保证在执行脚本时,脚本中的所有操作都会被当作一个不可分割的整体。具体来说,Redis 使用单线程的执行模型来处理命令,因此当 Lua 脚本在 Redis 中执行时,不会有其他命令打断脚本的执行过程。脚本中的所有操作都将连续执行,直到脚本执行完成后,Redis 才会继续处理其他客户端的请求。 Lua 脚本在 Redis 中原子性的原因

Smarty模板执行原理

为了实现程序的业务逻辑和内容表现页面的分离从而提高开发速度,php 引入了模板引擎的概念,php 模板引擎里面最流行的可以说是smarty了,smarty因其功能强大而且速度快而被广大php web开发者所认可。本文将记录一下smarty模板引擎的工作执行原理,算是加深一下理解。 其实所有的模板引擎的工作原理是差不多的,无非就是在php程序里面用正则匹配将模板里面的标签替换为php代码从而将两者

封装MySQL操作时Where条件语句的组织

在对数据库进行封装的过程中,条件语句应该是相对难以处理的,毕竟条件语句太过于多样性。 条件语句大致分为以下几种: 1、单一条件,比如:where id = 1; 2、多个条件,相互间关系统一。比如:where id > 10 and age > 20 and score < 60; 3、多个条件,相互间关系不统一。比如:where (id > 10 OR age > 20) AND sco

【Python知识宝库】上下文管理器与with语句:资源管理的优雅方式

🎬 鸽芷咕:个人主页  🔥 个人专栏: 《C++干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 文章目录 前言一、什么是上下文管理器?二、上下文管理器的实现三、使用内置上下文管理器四、使用`contextlib`模块五、总结 前言 在Python编程中,资源管理是一个重要的主题,尤其是在处理文件、网络连接和数据库

(function() {})();只执行一次

测试例子: var xx = (function() {     (function() { alert(9) })(); alert(10)     return "yyyy";  })(); 调用: alert(xx); 在调用的时候,你会发现只弹出"yyyy"信息,并不见弹出"10"的信息!这也就是说,这个匿名函数只在立即调用的时候执行一次,这时它已经赋予了给xx变量,也就是只是

Java程序到CPU上执行 的步骤

相信很多的小伙伴在最初学习编程的时候会容易产生一个疑惑❓,那就是编写的Java代码究竟是怎么一步一步到CPU上去执行的呢?CPU又是如何执行的呢?今天跟随小编的脚步去化解开这个疑惑❓。 在学习这个过程之前,我们需要先讲解一些与本内容相关的知识点 指令 指令是指导CPU运行的命令,主要由操作码+被操作数组成。 其中操作码用来表示要做什么动作,被操作数是本条指令要操作的数据,可能是内存地址,也

Android下执行linux命令

最近在开发过程中 使用了几个命令来对   手机的文件的权限进行修改;现在记录一下: 用到的方法: 1:判断是否有Root权限;  /**      * 判断当前手机是否有ROOT权限      * @return      */     public static boolean isRoot(){         boolean bool = false;         try{

main函数执行前、后再执行的代码

一、main结束 不代表整个进程结束  (1)全局对象的构造函数会在main 函数之前执行,          全局对象的析构函数会在main函数之后执行;          用atexit注册的函数也会在main之后执行。  (2)一些全局变量、对象和静态变量、对象的空间分配和赋初值就是在执行main函数之前,而main函数执行完后,还要去执行一些诸如释放空间、释放资源使用权等操作   (3)