概念

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

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

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

    - 建立 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. luogu_P3313 [SDOI2014]旅行

    传送门 Solution 第二次学习可持久化线段树 打了一道裸题来练习一下-- 对于每个宗教都可以开一个主席树 基础操作 树剖lca Code  #include<bits/stdc++.h&g ...

  2. windows命令行操作

    一.打开方式 -  开始菜单  -->  运行 -->  输入cmd -->  回车 二.常用的指令 dir                             - 列出当前目录 ...

  3. polarssl rsa & aes 加密与解密<转>

    上周折腾加密与解密,用了openssl, crypto++, polarssl, cyassl, 说起真的让人很沮丧,只有openssl & polarssl两个库的RSA & AES ...

  4. Jira 入门【转】

    JIRA是Atlassian公司出品的项目与事务跟踪工具,被广泛应用于缺陷跟踪.客户服务.需求收集.流程审批.任务跟踪.项目跟踪和敏捷管理等工作领域.它是一个集 项目计划.任务分配.需求管理.错误跟踪 ...

  5. Tosca 给定义变量,取内容放到变量里

    可以在TOOLS里 buffer viewer里面搜索查自己的变量

  6. ubuntu下如何开机自动执行自定义脚本?

    答: 将自定义脚本(假设自定义的脚本绝对路径为~/start_test.sh)添加到/etc/init.d/目录下,并更新系统启动项,命令如下: sudo cp ~/start_test.sh /et ...

  7. org.slf4j:slf4j-api:添加日志管理

    org.slf4j:slf4j-api:添加日志管理 转 https://blog.csdn.net/wolfking0608/article/details/77855624   一个好的程序, 完 ...

  8. 基于keras的triplet_loss

    https://blog.csdn.net/yjy728/article/details/79570554 https://blog.csdn.net/yjy728/article/details/7 ...

  9. Spring cloud微服务安全实战-3-6API安全机制之数据校验

    校验:非空.唯一性等校验 密码的加密:密码加密来存储. 如何做https的访问 校验 一个层面是接口层面,另外一个层面是数据库层面. Springboot给我们提供了简单的封装 校验的包里面还有其他的 ...

  10. Egret中的对象池Pool

    为了可以让对象复用,防止大量重复创建对象,导致资源浪费,使用对象池来管理. 一 对象池A 二 对象池B 一 对象池A 1. 支持传入构造函数 2. 支持预先创建对象 3. 支持统一执行函数 /** * ...