zoukankan      html  css  js  c++  java
  • 为什么我只查一行的语句,执行的还是这么慢?

    有些情况,只查一行数据,执行的也会特别慢,接下来我们就梳理一下,会出现这里现象的场景。

    数据库压力

    如果MySQL数据库本身就有很大的压力,导致CPU占用率很高,IO利用率很高,那么即使是执行一条SQL语句,也会执行的很慢。

    如果这条SQL语句被锁住,他就会执行的很慢。而MySQL中的锁,又分为全局锁、表级锁、行锁。首先我们会构建一个表,接下来我们会分情况进行分析。
    CREATE TABLE `t` (
      `id` int(11) NOT NULL,
      `c` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    
    delimiter ;;
    create procedure idata()
    begin
      declare i int;
      set i=1;
      while(i<=100000) do
        insert into t values(i,i);
        set i=i+1;
      end while;
    end;;
    delimiter ;
    
    call idata();

    全局锁

    全局锁的执行语句是:
    flush tables with read lock; 
    flush tables t with read lock;
    如果指定了表t,代表的是只关闭表t,如果没有指定表名,则表示关闭MySQL里所有打开的表。
    但是这个操作是加全局的写锁,使整个表处于只读的状态,不会阻塞查询语句。如果查询语句被阻塞,那么一定是这行命令被其他命令阻塞了,接下来我们来复现这个场景。
    我们可以通过show processlist来查看语句执行状态:
    可以看到 id为27,28的语句都id为26的语句被阻塞了,所以我们只要kill掉26号语句,即可解决这个问题,返回执行结果。

    表级锁

    如果有一个线程正在表t上请求或持有MDL写锁,就会把select语句阻塞住。
    但是这种场景只能在 MySQL5.6版本复现,而MySQL5.7版本就修改了MDL加锁的策略,而是采用了Online DDL的方式对表结构进行修改(CopyOnWrite)所以这里我们可以使用给表加写锁的方式复现。
    通过processlist来查看执行状态:
    31pid的语句状态处于等待元数据锁。我们可以在MySQL启动时设置performance_schema=on;(相比设置为off会有10%左右的性能损失)我们可以直径通过sys.schema_table_lock_waits这张表,找到造成阻塞的process id;kill掉即可。

    行锁

    select * from t where id=1 lock in share mode;
    如果我们访问id=1这个记录时,加了读锁,这个时候其他事物持有了写锁,我们的select语句就会被阻塞。
    我们通过processlist可以查询到语句执行状态:
    SessionA启动了事物,更改了数据,SessionB查询这条数据的时候,由于SessionA还没有提交事物。导致SessionB获取不到最新的数据(当前读)被阻塞。(读写锁阻塞)
    接下来我们要找到是谁占着这个写锁,如果我们使用的MySQL版本是5.7,则可以通过sys.innodb_lock_waits查到。
    select * from t sys.innodb_lock_waits where locked_table=`'test'.'t'`G
    kill掉相应线程即可。

    慢查询

    如果一个查询(当前读)伴随着一个长事务大量的修改,那么这个查询操作就会非常的慢。
    SessionB的update操作,会产生大量的回滚日志,SessionA的
    select * from t where id = 1;
    是一致性读,即基于MySQL事务开启时,所产生的一致性视图。所以返回的结果是1,并且查询非常快。
    而SessionA的
    select * from t where id = 1 lock in share mode;
    是当前读,需要等待SessoinB的100万次update操作,提交事物后,再根据回滚日志查询到当前值。
    所以执行的就会非常慢。
     

  • 相关阅读:
    php和c++自带的排序算法
    谷歌Chrome浏览器离线安装包
    js阻止表单提交
    Sublime text中文乱码解决办法
    不会飞的鸟
    linux命令**50
    linux基础2
    linux基础1
    css3实现单行文本溢出显示省略号
    null和undefined的区别
  • 原文地址:https://www.cnblogs.com/nedulee/p/11834246.html
Copyright © 2011-2022 走看看