存档

文章标签 ‘mysql sending data’

select *导致的mysql线程sending data

2017年6月17日 没有评论

今天因为公司618活动到公司值班,早上10点钟左右的时候,领导突然跑过来说”select * from xxx”导致数据库服务器负载飙升,让我看一下什么问题。当时由于紧张还看错了表名,看成另外一张表,后来联系公司dba,又让他发了一遍引起数据库负载飙升的sql,发现原来是活动开始以后,大量查询活动信息引起的问题。

我们的活动信息表里面有大量的城市id和活动的表述信息,而当有大量的”select * from xxx”存在时,虽然这个表的数据量不是很大,只有区区几千条记录记录,但是大量的查询引起mysql线程状态卡在”sending data”时,服务器的负载就上来了。

那么什么是”sending data”状态哪?其实这是一个很容易引起误导的状态说明,”sending data”是包含读取数据+发送数据的。这里以innodb存储引擎来说,我们在使用索引找到我们所需的记录时,期初得到是索引列信息和主键信息,如果我们查询的信息索引列中已经包含,那么万事大吉,mysql会把这些信息发送给客户端。但是如果像我的例子中的是使用”select *”这种情况,或者要索引列中未包含我们需要需要的更多信息,那么这时mysql就会拿着主键id去数据行获取信息,然后再把些信息发送给客户端。

现在回到上面的问题,我们数据表记录数不多,为什么会引起”sending data”哪?我们活动信息表有几个字段是MEDIUMTEXT或者VARCHAR(3000)类似这种要存储比较长字符串内容的字段,所以在使用”select *”时我们把本来不需要,但是却占用很大空间的字段也返回了,造成了大量无用的IO操作,这里包含读取数据和发送数据。由于接口我们使用的是被动缓存,所以活动刚开始时这些请求都打到了数据库,后面接口缓存生效以后数据库压力就降下来了。

开发框架使用的是Lumen,而且我们主要使用的是里面的ORM-Elopment,有些地方没有注意查询时设定字段就引起了这个问题,说句实话以前在使用ORM时,我一直没有养成限制返回字段的习惯。希望看到这篇文章的同学也能引以为戒,以后尽量不要使用”seleect *”这样粗暴的查询方式。