查询长时间不返回:MDL or flush tables
查询慢:查询时,该行数据被另一个事务修改,需要读 undolog

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

SELECT * FROM t WHERE id = 1;

情况一 :等 MDL 锁

前提知识 —— 表级锁

19.问题定位:为什么只查一行的语句也很慢-1.png|600

使用 show processlist 命令查看 Waiting for table metadata lock 的示意图。

出现这个状态表示的是,现在有一个线程正在表 t 上请求或持有 MDL 写锁,把 select 语句堵住了。

例如下面的情况:

session Asession B
lock table t write;
select * from t where id = 1;

这类问题的处理方式,就是找到谁持有 MDL 写锁,然后把它 kill 掉。

但是,由于在 show processlist 的结果里面,session A 的 Command 列是 “Sleep”,导致查找起来很不方便。不过有了 performance_schemasys 系统库以后,就方便多了。(MySQL 启动时需要设置 performance_schema=on)

通过查询 sys.schema_table_lock_waits 这张表,我们就可以直接找出造成阻塞的 process id,把这个连接用 kill 命令断开即可。

19.问题定位:为什么只查一行的语句也很慢-2.png|600

Flush tables

SELECT * FROM information_schema.processlist WHERE id=1;

19.问题定位:为什么只查一行的语句也很慢-3.png|600

这个状态表示的是,现在有一个线程正要对表 t 做 flush 操作。MySQL 里面对表做 flush 操作的用法,一般有以下两个:

flush tables t with read lock;
flush tables with read lock;

这两个 flush 语句,如果指定表 t 的话,代表的是只关闭表 t;如果没有指定具体的表名,则表示关闭 MySQL 里所有打开的表。

但是正常这两个语句执行起来都很快,除非它们也被别的线程堵住了。所以,出现 Waiting for table flush 状态的可能情况是:有一个 flush tables 命令被别的语句堵住了,然后它又堵住了我们的 select 语句。

第二类:查询慢

其他事务修改过于频繁,导致需要读 undolog

问题定位:为什么一个select语句也很慢.png|600

问题定位:为什么一个select语句也很慢-1.png|600

正在 Redolog 日志 刷脏页

具体参考 『发展经历』丁奇的 MySQL 心路历程 中的示例。

大量删除数据导致

问题定位:慢查询定位 2 —— 大量删除导致