阿里云RDS的内存增高与临时表

正文

mysql查看当前内存使用细节的语句是:

1
2
3
show variables where variable_name in (
'innodb_buffer_pool_size','innodb_log_buffer_size','innodb_additional_mem_pool_size','key_buffer_size','query_cache_size'
);

大部分内存占用告警,都是因为buffer pool增长导致,而buffer pool的增长是正常的,如图:
akb48

如果说这个值高的令人发指(超过90%),那么基本就是两种可能:

  1. 当前session太多,show full processlist;看一下是不是有太多空闲的对话,如果有,酌情调整timeout断开;
  2. session不多,但是session里的私有内存占用过多,那么就要检查一下对应的sql语句,是不是语句里有大量的临时表、sort(排序)和join操作;

如何判断是否使用了临时表?使用explain查看执行的sql语句,在Extra列看到Using temporary就意味着使用了临时表。比如这个:
akb48

一般情况下,用到临时表就意味着性能较低。查看临时表大小的语句是show global variables like '%table_size%';

如果说某个SQL语句,它查询的内容非常的多(select *这种的),然后又对这个查询的内容进行了二次加工(sort或者join)就会生成一个巨大的临时表,那么内存可能就会放不下,导致mysql将这个表全部放到磁盘里,那么这样mysql的IO就会出现飙升、sql执行缓慢的现象。

查看临时表是在内存还是在磁盘上,可以通过show global status like '%Created_tmp%';

1
2
3
4
5
6
7
8
9
MySQL [(none)]>  show global status like '%Created_tmp%';
+-------------------------+-----------+
| Variable_name | Value |
+-------------------------+-----------+
| Created_tmp_disk_tables | 53585768 | #服务器在磁盘上创建表(最初或通过转换内存中的表)
| Created_tmp_files | 807803 |
| Created_tmp_tables | 167011673 | #服务器创建内部临时表(在内存或磁盘上)
+-------------------------+-----------+
3 rows in set (0.00 sec)

遇到这样的情况,建议是将原语句拆成两个sql,然后用in操作拼接。

最后结论,MYSQL在上线部署后,导致内存激增,请检查是否出现了临时表。临时表如果大出了指定范围,写入到磁盘里,就会导致IO上升,拖垮SQL执行速度。

补充

在网站开发里,排序究竟是在程序(PHP)里排还是在数据库(mysql)里排?

在 PHP 中执行排序更优的情况举例如下:

  1. 数据源不在MySQL中,存在硬盘、内存或者来自网络的请求等;
  2. 数据存在MySQL中,量不大,而且没有相应的索引,此时把数据取出来用PHP排序更快;
  3. 数据源来自于多个MySQL服务器,此时从多个MySQL中取出数据,然后在PHP中排序更快;
  4. 除了MySQL之外,存在其他数据源,比如硬盘、内存或者来自网络的请求等,此时不适合把这些数据存入MySQL后再排序。

必须在MySQL中排序的实例如下:

  1. MySQL中已经存在这个排序的索引;
  2. MySQL中数据量较大,而结果集需要其中很小的一个子集,比如1000000行数据,取TOP10;
  3. 对于一次排序、多次调用的情况,比如统计聚合的情形,可以提供给不同的服务使用,那么在MySQL中排序是首选的。另外,对于数据深度挖掘,通常做法是在应用层做完排序等复杂操作,把结果存入MySQL即可,便于多次使用。
  4. 不论数据源来自哪里,当数据量大到一定的规模后,由于占用内存的关系,不再适合PHP中排序了;此时把数据复制、导入或者存在MySQL,并用INDEX优化,是优于PHP的。不过,用Java,甚至C++ 来处理这类操作会更好。

结论:从网站整体考虑,就必须加入人力和成本的考虑。假如网站规模和负载较小,而人力有限(人数和能力都可能有限),此时在应用层(PHP)做排序要做不少开发和调试工作,耗费时间,得不偿失;不如在 DB 中处理,简单快速。对于大规模的网站,电力、服务器的费用很高,在系统架构上精打细算,可以节约大量的费用,是公司持续发展之必要;此时如果能在应用层 (PHP) 进行排序并满足业务需求,尽量在应用层进行。

参考资料

https://dp.imysql.com:8080/node/97
http://mysql.taobao.org/monthly/2019/04/01/
http://blog.sae.sina.com.cn/archives/4096

感谢您请我喝咖啡~O(∩_∩)O,如果要联系请直接发我邮箱chenx1242@163.com,我会回复你的
-------------本文结束感谢您的阅读-------------