《Mysql - 为什么只查一行的数据,也这么慢?》
概念
- 在某些情况下,“查一行”,也会执行得特别慢。
- 下面分析在什么情况下,会出现这个现象。
- 基础工作(构建数据库环境)
- 建立 t 表,并写入 10W 的数据。
CREATE TABLE `t` (
`id` int() NOT NULL,
`c` int() DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;
delimiter ;;
create procedure idata()
begin
declare i int;
set i=;
while(i<=) do
insert into t values(i,i);
set i=i+;
end while;
end;;
delimiter ;
第一类:查询长时间不返回?
- 表现
- 
- 分析
- 一般碰到这种情况的话,大概率是表 t 被锁住了。
- 接下来分析原因的时候,一般都是首先执行一下 show processlist 命令,看看当前语句处于什么状态。
一:等待MDL锁
- Show processlist 状态。
- 
- 状态解读
- 这个状态表示的是,现在有一个线程正在表 t 上请求或者持有 MDL 写锁,把 select 语句堵塞了。
- 场景复现
- 
- 原理
- session A 通过 lock table 命令持有表 t 的 MDL 写锁,而 session B 的查询需要获取 MDL 读锁。所以,session B 进入堵塞状态。
- 解决办法
- 这类问题的处理方式,就是找到谁持有 MDL 写锁,然后把它 kill 掉。
- 但是,由于在 show processlist 的结果里面,session A 的 Command 列是“Sleep”,导致查找起来很不方便。
- 不过有了 performance_schema 和 sys 系统库以后,就方便多了。(MySQL 启动时需要设置 performance_schema=on,相比于设置为 off 会有 10% 左右的性能损失)
- select * from sys.schema_table_lock_waits \G;
- 
二:刷 flush
- Show processlist 状态。
- 
- 解读状态
- 这个状态表示的是,现在有一个线程正要对表 t 做 flush 操作。
- MySQL 里面对表做 flush 操作的用法,一般有以下两个:
- flush tables t with read lock; // 指定表,则代表只是关闭表 t
- flush tables with read lock; // 未指定表,则表示关闭 MySQL 里所有打开的表。
- 但是正常这两个语句执行起来都很快,除非它们也被别的线程堵住了。
- 所以,出现 Waiting for table flush 状态的可能情况是:有一个 flush tables 命令被别的语句堵住了,然后它又堵住了我们的 select 语句。
- 场景复现
- 
- 原理
- 在 session A 中,我故意每行都调用一次 sleep(1),这样这个语句默认要执行 10 万秒,在这期间表 t 一直是被 session A“打开”着。
- 然后,session B 的 flush tables t 命令再要去关闭表 t,就需要等 session A 的查询结束。
- 这样,session C 要再次查询的话,就会被 flush 命令堵塞了。
- 解决办法
- 找到谁一直长时间的占有表,导致表不能正常关闭,kill 掉他。
- 
三: 等行锁
- Show processlist 状态。
- 
- 状态解读
- 由于事务A加读锁,如果这时候已经有一个事务在这行记录上持有一个写锁,我们的事务A就会被堵塞。
- 场景复现
- 
- 原理
- session A 启动了事务,占有写锁,还不提交,是导致 session B 被堵塞的原因。
- 解决办法
- select * from sys.innodb_lock_waits \G; // 找到锁占用
- 
- 可以看到,13 号线程是造成堵塞的罪魁祸首。通过 KILL QUERY 4 或 KILL 4。
- 不过,“KILL QUERY 13” 是无法停止这个死锁的。因为这个命令表示停止 4 号线程当前正在执行的语句,
- 但是因为占有行锁的是 update 语句,这个语句已经是之前执行完成了的,现在执行 KILL QUERY,无法让这个事务去掉 id=1 上的行锁。
- 实际上,KILL 13 才有效,也就是说直接断开这个连接,连接被断开的时候,占有行锁的将自动回滚,释放锁资源。
第二类:查询慢
- 解决办法
- explain 分析,使用合适的索引
- slow log 慢日志开启,找到慢日志。
- 注意 redo log 对执行的影响(不常见)
《Mysql - 为什么只查一行的数据,也这么慢?》的更多相关文章
- 简单物联网:外网访问内网路由器下树莓派Flask服务器
最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...
- 利用ssh反向代理以及autossh实现从外网连接内网服务器
前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...
- 外网访问内网Docker容器
外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...
- 外网访问内网SpringBoot
外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...
- 外网访问内网Elasticsearch WEB
外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...
- 怎样从外网访问内网Rails
外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...
- 怎样从外网访问内网Memcached数据库
外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...
- 怎样从外网访问内网CouchDB数据库
外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...
- 怎样从外网访问内网DB2数据库
外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...
- 怎样从外网访问内网OpenLDAP数据库
外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...
随机推荐
- JS中的constructor 和 prototype
object.constructor :对象的constructor 属性引用了该对象的构造函数. //例如,用Array()构造函数创建了一个数组,那么a.constructor 引用的就是Arra ...
- tensorflow中的函数获取Tensor维度的两种方法:
获取Tensor维度的两种方法: Tensor.get_shape() 返回TensorShape对象, 如果需要确定的数值而把TensorShape当作list使用,肯定是不行的. 需要调用Tens ...
- Oracle语法 及 SQL题目(一)
目录 课例复制 SQL题目一 SQL题目二 SQL题目三 笔记 课例复制 OCM 全称:Oracle Certified Master 认证大师 含义:Oracle 原厂推出的数据库方向最高级别认证 ...
- ORACLE AUDIT
Oracle 作者:Davis_itpub 时间:2018-06-27 16:28:39 61 0 审计(Audit)用于监视用户所执行的数据库操作,并且Oracle 会将审计跟踪结果存放到OS ...
- JS实现文字向上无缝滚动轮播
效果图: 全部代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...
- Spring源码之DefaultListableBeanFactory及资源载入
1.XmlBeanFactory 的使用,参考MyEclipse Spring 学习总结一 Spring IOC容器 public static void main(String[] args) { ...
- 树莓派 more
树莓派 rusthttps://tech.iotcomeon.com/2018/06/tech/deploy/515/sudo curl https://sh.rustup.rs -sSf | sh ...
- Dart静态方法、对象操作符和类的继承
/* Dart中的静态成员: 1.使用static 关键字来实现类级别的变量和函数 2.静态方法不能访问非静态成员,非静态方法可以访问静态成员 */ // class Person { // stat ...
- 泡泡一分钟:Robust and Fast 3D Scan Alignment Using Mutual Information
Robust and Fast 3D Scan Alignment Using Mutual Information 使用互信息进行稳健快速的三维扫描对准 https://arxiv.org/pdf/ ...
- 修复gitlab服务器突然停电导致PostgreSQL损坏的数据库
最开始是存储的卷组受损,使用的DRBD,使用了xfs分区格式: 挂载也报错: mount /dev/drbd0 /var/opt mount: wrong fs type, bad option, b ...