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

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

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 语句。

偶尔比较慢
1, 数据库更新数据时是在内存中更新数据,并将更新的数据写到 redolog 中,最后再持久化到磁盘中。如果数据库一直很忙,没有将 redolog 更新到磁盘中,那么待到 redolog 大小达到限额时,数据库会停下来先将 redolog 持久化到磁盘。没有解决方法
2, 该语句一时半会一直没拿到锁,因此一直在等待。没有解决方法

一直很慢
1, 字段没有索引,走的全表查询,建立索引。
2, 字段有索引但是没用上,包括,where 中计算语句、函数使用、联合索引第一个为范围查找,更改语句或修改索引顺序等。
3, 系统选错索引了,根据内置优化,以为索引 a 合适,但是实际索引 b 更合适。

大量删除导致 limit 1 一直遍历

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