zoukankan      html  css  js  c++  java
  • 《Mysql

    概念

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

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

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

        - 建立 t 表,并写入 10W 的数据。

      • 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 ;

    第一类:查询长时间不返回

      - 表现

        - 

      

      -  分析

        - 一般碰到这种情况的话,大概率是表 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 对执行的影响(不常见)

  • 相关阅读:
    postgresql数据迁移
    编译安装或者mysql启动时遇到的错误小记
    安装数据库时提示重启删除 以下注册信息则不用重启
    ​sql2008安装提示报错,.必须使用"角色管理工具"安装或配置Microsoft.net.framework 3.5 sp1
    windows10 安装jdk13.0.1 与 apache-jmeter-5.1.1
    Axure RP 9 获取验证码发送倒计时
    PHP 重定向跳转页面使用post传参
    用 PHPExcel 导入excel表格并展示到前台
    当失去焦点时 验证时分秒 并提示
    iptables 防止syn ddos ping攻击
  • 原文地址:https://www.cnblogs.com/25-lH/p/11017966.html
Copyright © 2011-2022 走看看