『MySQL 实战 45 讲』19 - 为什么我只查一行的语句,也执行这么慢?

2024-05-03 06:28

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

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

  1. 需求:创建一个表,有两个字段 id 和 c,并且在里面插入了 10 万行记录
CREATE TABLE `t` (`id` int(11) NOT NULL,`c` int(11) DEFAULT NULL,PRIMARY KEY (`id`)
) ENGINE=InnoDB;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();

查询长时间不返回

  1. 执行下面语句,长时间不返回
select * from t where id=1;
  1. 大概率是表 t 被锁住了,需要通过执行 show processlist 命令,查看语句得状态

等 MDL 锁

  1. 使用 show processlist 命令查看 Waiting for table metadata lock
    在这里插入图片描述
  2. 出现这个状态表示的是,现在有一个线程正在表 t 上请求或者持有 MDL 写锁,把 select 语句堵住了
  3. 复现场景
    在这里插入图片描述
  4. 解决办法就是找到持有 MDL 写锁的线程,然后 kill 掉
  • 通过 show processlist 只能看到 Command 是 “sleep”
  • 需要设置 performance_schema=on(相比于设置为 off 会有 10% 左右的性能损失,查询 sys.schema_table_lock_waits 表,找到 process id
# 查询是否开启
show variables like 'performance_schema'
# 找到有 MDL 写锁的线程
select blocking_pid from sys.schema_table_lock_waits;

等 flush

  1. MYSQL 里面对表做 flush 操作一般有以下两个
# 只关闭表 t
flush tables t with read lock;
# 关闭 MySQL 里所有打开的表
flush tables with read lock;
  1. Waiting for table flush 的复现步骤
    在这里插入图片描述
  2. 通过 show processlist 可以知道结果,从而排查问题
    在这里插入图片描述

等行锁

  1. 行锁复现
    在这里插入图片描述
  2. show processlist 现场
    在这里插入图片描述
  3. 但是是查不到谁在占用这个写锁,可以通过下面命令来看
select * from sys.innodb_lock_waits where locked_table='`testdb`.`t`'\G

在这里插入图片描述
4. 可以看出 905 号线程是问题根源,可以执行 KILL QUERY 905 或者 KILL 905

  • KILL QUERY 905:表示停止 905 号线程当前正在执行的语句,而这个方法其实是没有用的。因为占有行锁的是 update 语句,这个语句已经是之前执行完成了的,现在执行 KILL QUERY,无法让这个事务去掉 id=1 上的行锁
  • KILL 905:实际上,该命令才有效,也就是说直接断开这个连接。这里隐含的一个逻辑就是,连接被断开的时候,会自动回滚这个连接里面正在执行的线程,也就释放了 id=1 上的行锁

查询慢

  1. 扫描行数多,执行慢。通过查看慢查询日志,Rows_examined 可以看到扫描过的量
# 开启慢查询日志
SET GLOBAL slow_query_log=1;
# 查询是否开启慢查询日志
SHOW VARIABLES LIKE '%slow_query_log%';
# 设置慢查询时间
set long_query_time = 0;select * from t where c=50000 limit 1;

在这里插入图片描述
2. 扫描 1 行但是执行还是很慢的情况

  • 复现步骤,其中会话 B 执行了 100w 次
    在这里插入图片描述
  • 这时候选择执行 select * from t where id=1 会很慢,执行 select * from t where id=1 lock in share mode 会很快
  • 因为生成了 100w 个回滚日志
    在这里插入图片描述

这篇关于『MySQL 实战 45 讲』19 - 为什么我只查一行的语句,也执行这么慢?的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

网页解析 lxml 库--实战

lxml库使用流程 lxml 是 Python 的第三方解析库,完全使用 Python 语言编写,它对 XPath表达式提供了良好的支 持,因此能够了高效地解析 HTML/XML 文档。本节讲解如何通过 lxml 库解析 HTML 文档。 pip install lxml lxm| 库提供了一个 etree 模块,该模块专门用来解析 HTML/XML 文档,下面来介绍一下 lxml 库

SQL中的外键约束

外键约束用于表示两张表中的指标连接关系。外键约束的作用主要有以下三点: 1.确保子表中的某个字段(外键)只能引用父表中的有效记录2.主表中的列被删除时,子表中的关联列也会被删除3.主表中的列更新时,子表中的关联元素也会被更新 子表中的元素指向主表 以下是一个外键约束的实例展示

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

如何去写一手好SQL

MySQL性能 最大数据量 抛开数据量和并发数,谈性能都是耍流氓。MySQL没有限制单表最大记录数,它取决于操作系统对文件大小的限制。 《阿里巴巴Java开发手册》提出单表行数超过500万行或者单表容量超过2GB,才推荐分库分表。性能由综合因素决定,抛开业务复杂度,影响程度依次是硬件配置、MySQL配置、数据表设计、索引优化。500万这个值仅供参考,并非铁律。 博主曾经操作过超过4亿行数据

性能分析之MySQL索引实战案例

文章目录 一、前言二、准备三、MySQL索引优化四、MySQL 索引知识回顾五、总结 一、前言 在上一讲性能工具之 JProfiler 简单登录案例分析实战中已经发现SQL没有建立索引问题,本文将一起从代码层去分析为什么没有建立索引? 开源ERP项目地址:https://gitee.com/jishenghua/JSH_ERP 二、准备 打开IDEA找到登录请求资源路径位置

MySQL数据库宕机,启动不起来,教你一招搞定!

作者介绍:老苏,10余年DBA工作运维经验,擅长Oracle、MySQL、PG、Mongodb数据库运维(如安装迁移,性能优化、故障应急处理等)公众号:老苏畅谈运维欢迎关注本人公众号,更多精彩与您分享。 MySQL数据库宕机,数据页损坏问题,启动不起来,该如何排查和解决,本文将为你说明具体的排查过程。 查看MySQL error日志 查看 MySQL error日志,排查哪个表(表空间

C#实战|大乐透选号器[6]:实现实时显示已选择的红蓝球数量

哈喽,你好啊,我是雷工。 关于大乐透选号器在前面已经记录了5篇笔记,这是第6篇; 接下来实现实时显示当前选中红球数量,蓝球数量; 以下为练习笔记。 01 效果演示 当选择和取消选择红球或蓝球时,在对应的位置显示实时已选择的红球、蓝球的数量; 02 标签名称 分别设置Label标签名称为:lblRedCount、lblBlueCount

MySQL高性能优化规范

前言:      笔者最近上班途中突然想丰富下自己的数据库优化技能。于是在查阅了多篇文章后,总结出了这篇! 数据库命令规范 所有数据库对象名称必须使用小写字母并用下划线分割 所有数据库对象名称禁止使用mysql保留关键字(如果表名中包含关键字查询时,需要将其用单引号括起来) 数据库对象的命名要能做到见名识意,并且最后不要超过32个字符 临时库表必须以tmp_为前缀并以日期为后缀,备份

[MySQL表的增删改查-进阶]

🌈个人主页:努力学编程’ ⛅个人推荐: c语言从初阶到进阶 JavaEE详解 数据结构 ⚡学好数据结构,刷题刻不容缓:点击一起刷题 🌙心灵鸡汤:总有人要赢,为什么不能是我呢 💻💻💻数据库约束 🔭🔭🔭约束类型 not null: 指示某列不能存储 NULL 值unique: 保证某列的每行必须有唯一的值default: 规定没有给列赋值时的默认值.primary key:

滚雪球学Java(87):Java事务处理:JDBC的ACID属性与实战技巧!真有两下子!

咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE啦,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~ 🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,助你一臂之力,带你早日登顶🚀,欢迎大家关注&&收藏!持续更新中,up!up!up!! 环境说明:Windows 10