欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  数据库

MySQL内存不释放_MySQL

程序员文章站 2022-05-02 13:09:37
...
前几天业务线发现一例MySQL数据库内存增长异常案例,现象如下:
数据库版本:Percona MySQL 5.0.67
数据量:670M+
内存大小:16G
Innodb Buffer Pool Size:4G
其它回话内存分配并不大,基本在100M以内,并且连接数非常少
服务器负载不高,开启Binlog,数据库和程序都已经进行过迁移,问题仍然存在。通过top命令查看MySQL占用内存一直在增长,且开始使用Swap。

分析排除过程:
1.怀疑到的是InnoDB内存占用,使用show engine innodb status查看,发现Free Buffer占很大部分,因此可以判断分配给Innodb引擎的内存够用
2.查看回话,回话数基本在3~4个,且回话分配的内存大小与现在MySQL占用的回话总和相差很大,因此也不会是回话的问题
3.程序、数据库软件问题。已经迁移过两次,版本与外网一致,问题依旧,因此也排除了这个问题
4.MySQL重启后内存释放,因此问题还是在MySQL身上,根据网上说的Flush Tables的做法发现无效,所以也不是打开的表数量过大的问题导致。

就在临时维护前1小时,网上查找案例时,有人说内存表配置不当也有可能导致内存异常,但因为天龙没有用到Memory引擎,因此没太在意,但已经山穷水尽,也不知道该做什么,就查了下数据库中Innodb以外的表,主要集中在mysql库及information_schema库:
+——————–+—————————————+——–+
| TABLE_SCHEMA | TABLE_NAME | ENGINE |
+——————–+—————————————+——–+
| information_schema | CHARACTER_SETS | MEMORY |
| information_schema | CLIENT_STATISTICS | MEMORY |
| information_schema | COLLATIONS | MEMORY |
| information_schema | COLLATION_CHARACTER_SET_APPLICABILITY | MEMORY |
| information_schema | COLUMNS | MyISAM |
……
| mysql | help_topic | MyISAM |
| mysql | time_zone | MyISAM |
| mysql | time_zone_leap_second | MyISAM |
| mysql | time_zone_name | MyISAM |
| mysql | time_zone_transition | MyISAM |
| mysql | time_zone_transition_type | MyISAM |
| mysql | user | MyISAM |
+——————–+—————————————+——–+
因为MyISAM表不多,而且表都不大,内存分配也没有问题,所以我大概过了一遍,剩下的就是MEMORY 表了。
单独对这些表进行查看,最终发现CLIENT_STATISTICS表非常异常,原因是作为内存表查询速度非常慢,,并且会报错,在/tmp/下的一个临时文件需要修复,因此到/tmp目录下进行查看,基本就定位到问题了:导出的临时表约为7~8G!
查看表数据基本不可能,因此在维护时,重启了数据库,并且查看了里面的数据,发现数据增长非常快,里面记录的都是客户端的连接记录,比较特别的就是主机名显示不全。因此我们选择将主机名改成IP的形式,用于定位出问题的服务器(当时还在怀疑是程序连接中断导致记录数增长)。但修改完后发现问题消失了,该台服务器与其他服务器区别,问题表的数据量也正常了,因此我们定位问题到了主机名上,我进行了一下实验:

现在有245、246两台机器:
246是客户端、245是服务器端
(root:245:Thu Apr 24 16:37:28 2014)[information_schema]> select count(*) from CLIENT_STATISTICS;
+———-+
| count(*) |
+———-+
| 2 |
+———-+
1 row in set (0.00 sec)
可以看到表里面的数据是2条

[dbatlbb@ ~]$ mysql -h 245 -uwuwl_test -p
mysql: Can’t create/write to file ‘/home/mysql/query.log’ (Errcode: 13)
Error logging to file ‘/home/mysql/query.log’
Logging to file ‘/home/dbatlbb/mysql/query.log’
Enter password:
Welcome to the MySQL monitor. Commands end with ; or /g.
Your MySQL connection id is 556
Server version: 5.0.67-percona-highperf-log Source distribution

Type ‘help;’ or ‘/h’ for help. Type ‘/c’ to clear the buffer.

(wuwl_test:${HOSTNAME}:Thu Apr 24 16:39:19 2014)[(none)]> show processlist;
+—–+———–+———————————+——+———+——+——-+——————+
| Id | User | Host | db | Command | Time | State | Info |
+—–+———–+———————————+——+———+——+——-+——————+
| 556 | wuwl_test | gs_438_friuha_fgesihs_fsd:50768 | NULL | Query | 0 | NULL | show processlist |
+—–+———–+———————————+——+———+——+——-+——————+
1 row in set (0.00 sec)
连接了一下,并进行了一次查询操作
(root:NJ-245:Thu Apr 24 16:38:38 2014)[information_schema]> select count(*) from CLIENT_STATISTICS;
+———-+
| count(*) |
+———-+
| 5 |
+———-+
1 row in set (0.01 sec)
发现数据有增长,再次进行几次查询,发现每次查询都会有增长,这个正常现象么?我修改了下主机名进行了再次查询,发现表数据不再增长。
修改方法:主机名需要小于16字节。
目前在5.5和5.6版本上进行了测试,发现这个表数据为空,因此这个问题可能是在5.0版本上面的一个BUG。

总结:
本次问题现象主要是:内存异常被MySQL占用不释放并持续上涨,更换过程序和数据库服务器仍没有效果,服务器数据量很小,Innodb Buffer空闲很大。
问题原因:由于数据库自身的统计数据表information_schema.CLIENT_STATISTICS 数据量过大导致内存占用,CLIENT_STATISTICS是一张内存表。
问题处理方法:由于CLIENT_STATISTICS表里面的Host列是16个字节的,因此如果主机名过长,会导致客户端每一次的操作都会在表里面新增一条数据,无论操作是否成功。因此只需要修改连接的主机名不要超过16位就不会导致内存占用不释放的问题。
思考:修改了默认的东西,需要在小部分服务器上进行测试,并详细记录修改后的异常,用于对比不同服务器之间的差别。

延伸:
CLIENT_STATISTICS 用于统计客户端连接,目前5.5、5.6以及Maria已经将client字段升级为64个字节,且该统计功能默认关闭,所以如果大家有统计需要,一定要记得主机名不能大于64个字节!

相关标签: 数据库