概念

  - 在某些情况下,“查一行”,也会执行得特别慢。

  - 下面分析在什么情况下,会出现这个现象。

  - 基础工作(构建数据库环境)

    - 建立 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 - 为什么只查一行的数据,也这么慢?》的更多相关文章

  1. 简单物联网:外网访问内网路由器下树莓派Flask服务器

    最近做一个小东西,大概过程就是想在教室,宿舍控制实验室的一些设备. 已经在树莓上搭了一个轻量的flask服务器,在实验室的路由器下,任何设备都是可以访问的:但是有一些限制条件,比如我想在宿舍控制我种花 ...

  2. 利用ssh反向代理以及autossh实现从外网连接内网服务器

    前言 最近遇到这样一个问题,我在实验室架设了一台服务器,给师弟或者小伙伴练习Linux用,然后平时在实验室这边直接连接是没有问题的,都是内网嘛.但是回到宿舍问题出来了,使用校园网的童鞋还是能连接上,使 ...

  3. 外网访问内网Docker容器

    外网访问内网Docker容器 本地安装了Docker容器,只能在局域网内访问,怎样从外网也能访问本地Docker容器? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Docker容器 ...

  4. 外网访问内网SpringBoot

    外网访问内网SpringBoot 本地安装了SpringBoot,只能在局域网内访问,怎样从外网也能访问本地SpringBoot? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装Java 1 ...

  5. 外网访问内网Elasticsearch WEB

    外网访问内网Elasticsearch WEB 本地安装了Elasticsearch,只能在局域网内访问其WEB,怎样从外网也能访问本地Elasticsearch? 本文将介绍具体的实现步骤. 1. ...

  6. 怎样从外网访问内网Rails

    外网访问内网Rails 本地安装了Rails,只能在局域网内访问,怎样从外网也能访问本地Rails? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Rails 默认安装的Rails端口 ...

  7. 怎样从外网访问内网Memcached数据库

    外网访问内网Memcached数据库 本地安装了Memcached数据库,只能在局域网内访问,怎样从外网也能访问本地Memcached数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装 ...

  8. 怎样从外网访问内网CouchDB数据库

    外网访问内网CouchDB数据库 本地安装了CouchDB数据库,只能在局域网内访问,怎样从外网也能访问本地CouchDB数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动Cou ...

  9. 怎样从外网访问内网DB2数据库

    外网访问内网DB2数据库 本地安装了DB2数据库,只能在局域网内访问,怎样从外网也能访问本地DB2数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动DB2数据库 默认安装的DB2 ...

  10. 怎样从外网访问内网OpenLDAP数据库

    外网访问内网OpenLDAP数据库 本地安装了OpenLDAP数据库,只能在局域网内访问,怎样从外网也能访问本地OpenLDAP数据库? 本文将介绍具体的实现步骤. 1. 准备工作 1.1 安装并启动 ...

随机推荐

  1. JS中的constructor 和 prototype

    object.constructor :对象的constructor 属性引用了该对象的构造函数. //例如,用Array()构造函数创建了一个数组,那么a.constructor 引用的就是Arra ...

  2. tensorflow中的函数获取Tensor维度的两种方法:

    获取Tensor维度的两种方法: Tensor.get_shape() 返回TensorShape对象, 如果需要确定的数值而把TensorShape当作list使用,肯定是不行的. 需要调用Tens ...

  3. Oracle语法 及 SQL题目(一)

    目录 课例复制 SQL题目一 SQL题目二 SQL题目三 笔记 课例复制 OCM 全称:Oracle Certified Master 认证大师 含义:Oracle 原厂推出的数据库方向最高级别认证 ...

  4. ORACLE AUDIT

    Oracle 作者:Davis_itpub 时间:2018-06-27 16:28:39  61  0 审计(Audit)用于监视用户所执行的数据库操作,并且Oracle 会将审计跟踪结果存放到OS ...

  5. JS实现文字向上无缝滚动轮播

    效果图: 全部代码: <!DOCTYPE html> <html lang="en"> <head> <meta charset=&quo ...

  6. Spring源码之DefaultListableBeanFactory及资源载入

    1.XmlBeanFactory 的使用,参考MyEclipse Spring 学习总结一 Spring IOC容器 public static void main(String[] args) { ...

  7. 树莓派 more

    树莓派 rusthttps://tech.iotcomeon.com/2018/06/tech/deploy/515/sudo curl https://sh.rustup.rs -sSf | sh ...

  8. Dart静态方法、对象操作符和类的继承

    /* Dart中的静态成员: 1.使用static 关键字来实现类级别的变量和函数 2.静态方法不能访问非静态成员,非静态方法可以访问静态成员 */ // class Person { // stat ...

  9. 泡泡一分钟:Robust and Fast 3D Scan Alignment Using Mutual Information

    Robust and Fast 3D Scan Alignment Using Mutual Information 使用互信息进行稳健快速的三维扫描对准 https://arxiv.org/pdf/ ...

  10. 修复gitlab服务器突然停电导致PostgreSQL损坏的数据库

    最开始是存储的卷组受损,使用的DRBD,使用了xfs分区格式: 挂载也报错: mount /dev/drbd0 /var/opt mount: wrong fs type, bad option, b ...