概念

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

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

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

    - 建立 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. Java IO管道流

    import java.io.IOException; import java.io.PipedInputStream; import java.io.PipedOutputStream; publi ...

  2. Spring的xml中引入其他文件

    引入db.properties <!--加载db.properties文件--> <context:property-placeholder location="class ...

  3. OpenFOAM-圆柱绕流

    原版视频下载地址:https://yunpan.cn/c64yrdt9J5LmQ  访问密码 0128 首先进行建模操作,任何建模软件均可,本教程采用ICEM直接建模,模型尺寸如下: 建成的模型如下: ...

  4. PHP如何解决网站大流量与高并发的问题(二)

    转载:https://zhyunfe.github.io/2017/10/02/php-interview-prepare-hc-2/ 数据库缓存 相关概念 什么是数据库缓存? 为什么使用缓存 使用M ...

  5. [设计原则与模式] 面向对象程序设计之五大原则(SOLID)

    cp from:  https://blog.csdn.net/zhangbuzhangbu/article/details/51719952 S.O.L.I.D是面向对象设计和编程(OOD& ...

  6. cmake 手册详解【转】

    https://www.cnblogs.com/coderfenghc/tag/cmake/   CMake 手册详解(二十三) SirDigit 2012-12-16 22:03 阅读:11058 ...

  7. Python 3.8.0 final¶ Release date: 2019-10-14

    https://docs.python.org/3.8/whatsnew/changelog.html#python-3-8-0 Core and Builtins bpo-38469: Fixed ...

  8. 积神经网络(CNN)的参数优化方法

    http://www.cnblogs.com/bonelee/p/8528863.html 积神经网络的参数优化方法——调整网络结构是关键!!!你只需不停增加层,直到测试误差不再减少. 积神经网络(C ...

  9. iptables 配置 场景1

    这样配置完成后,没法完成本地回环,需要对lo网卡进行配置 本地报文无法发出,继续添加规则

  10. flutte的第一个hello world程序

    用命令行创建项目: flutter create flutterdemo VSCode或者AS连接手机后 输入 flutter run 编译后就可以将默认的代码显示在手机上了 开始写hello wor ...