记一次 Linux Cache 异常事件
-
buff/cache 总是异常增长(一天增长 2 至 3 G)
-
MySQL 客户端时常会出现断开连接情况:
2013, ‘Lost connection to MySQL server during query’
2006, ‘MySQL server has gone away’
[root@mysql-redis ~]# hostnamectl
Static hostname: mysql-redis
Icon name: computer-vm
Chassis: vm
Machine ID: b62ee62249064ae3850030f860d1c36f
Boot ID: 76b979281b9247e794105d40bc18cf7b
Virtualization: vmware
Operating System: CentOS Linux 7 (Core)
CPE OS Name: cpe:/o:centos:centos:7
Kernel: Linux 3.10.0-862.3.2.el7.x86_64
Architecture: x86-64
[root@mysql-redis ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 323
Server version: 8.0.15 MySQL Community Server - GPL
首先是用 free -h 查看内存信息
[root@mysql-redis ~]# free -h
total used free shared buff/cache available
Mem: 7.6G 1.7G 3.5G 55M 2.4G 5.6G
Swap: 3.0G 2.8M 3.0G
使用 atop 查看一下内存分配
发现buff/cache的占用几乎全部为 Cache 使用(Buff为写入缓存;Cache 为读取缓存)
继续使用 slabtop 查看到底是那些使用了 Cache
上图可以发现proc_inode_cache 使用量一骑绝乘,遥遥领先
proc_inode_cache 代表 proc 文件系统的 inode 占用
使用 ps -e 发现进程不多;进一步使用 ps -eLf 查看线程
[root@mysql-redis ~]# ps -eLf
#----
#上面输出省略
#----
mysql 21659 1 21659 0 106 4月22 ? 00:00:16 /usr/sbin/mysqld
mysql 21659 1 21664 0 106 4月22 ? 00:01:29 /usr/sbin/mysqld
mysql 21659 1 21665 0 106 4月22 ? 00:01:29 /usr/sbin/mysqld
mysql 21659 1 21666 0 106 4月22 ? 00:01:34 /usr/sbin/mysqld
mysql 21659 1 21667 0 106 4月22 ? 00:01:33 /usr/sbin/mysqld
mysql 21659 1 21668 0 106 4月22 ? 00:01:36 /usr/sbin/mysqld
mysql 21659 1 21669 0 106 4月22 ? 00:01:35 /usr/sbin/mysqld
mysql 21659 1 21670 0 106 4月22 ? 00:01:46 /usr/sbin/mysqld
mysql 21659 1 21671 0 106 4月22 ? 00:01:35 /usr/sbin/mysqld
mysql 21659 1 21672 0 106 4月22 ? 00:01:32 /usr/sbin/mysqld
#----
#下面面输出省略
#----
发现了一百多个 MySQL 线程
👇计算一下 Socket
[root@mysql-redis ~]# ll /proc/21659/task/*/fd/ |grep socket |wc -l
6148
还在可接受返回之内
👇计算一下 fd
[root@mysql-redis ~]# ll /proc/21659/task/*/fd/ |wc -l
711895
这个就很操蛋了,接受不能啊!
再来看看到底都是啥玩意儿占用了这么多 fd
[root@mysql-redis ~]# ll /proc/21659/task/*/fd/
/proc/21659/task/1128/fd/:
总用量 0
lr-x------ 1 mysql mysql 64 5月 8 18:15 0 -> /dev/null
l-wx------ 1 mysql mysql 64 5月 8 18:15 1 -> /var/log/mysqld.log
lrwx------ 1 mysql mysql 64 5月 8 18:15 10 -> /db_apps/mysql/ibdata1
lrwx------ 1 mysql mysql 64 5月 8 18:15 100 -> /db_apps/mysql/rpa_management/rpa_api_group.MYD
lrwx------ 1 mysql mysql 64 5月 8 18:15 1000 -> /tmp/mysql_temptable.yes57Z (deleted)
lrwx------ 1 mysql mysql 64 5月 8 18:15 1001 -> /tmp/mysql_temptable.EWyyWI (deleted)
lrwx------ 1 mysql mysql 64 5月 8 18:15 1002 -> /tmp/mysql_temptable.z0Xs8A (deleted)
lrwx------ 1 mysql mysql 64 5月 8 18:15 1003 -> /tmp/mysql_temptable.26ywwO (deleted)
#----
#👇输出省略 多得吓死个人
#----
每个inode都是占用空间的,且proc文件系统是全内存的。 所以我们才会看到slab中proc_inode_cache内存占用高
在我经过各种 Google 之后发现了 [有人和我出现了似乎相同的情况](https://dba.stackexchange.com/questions/228403/mysql-crashing-at-about-70k-open-files
里面的回答提醒了我:
The issue is a Mysql bug (https://bugs.mysql.com/bug.php?id=94185 )
于是乎 我去翻看了 MySQL 8.0.16 的 [Change Log](https://dev.mysql.com/doc/relnotes/mysql/8.0/en/news-8-0-16.html
我发现了以下两个 fixs bug:
-
InnoDB: Optimized
InnoDB
internal temporary tables did not support in-placeUPDATE
operations, which caused the number of delete-marked records to increase continuously. The large number of delete-marked records could cause longer than expected query execution times. (Bug #29207450) -
InnoDB: The purge thread failed to free LOB data pages. (Bug #28510599)
inodb临时表 不能原地 update,会导致删除标记(也就是 mysql_temptable.26ywwO (deleted) )记录数量源源不断的增加。大量删除标记的记录会导致查询时间超过预期(这也是为什么客户端会出现各种报错的原因)!
清除线程无法释放 LOB 数据页(这也是 Cache 会源源不断增加的原因)
解决方式:将 MySQL 从 8.0.15 升级到 8.0.16
-
防止意外先备份数据库:
[root@mysql-redis ~]# mysqldump -uxxxx -pxxxxxx --all-databases --add-drop-table --add-locks > dump.sqlbash
-
升级 MYSQL
[root@mysql-redis ~]# yum update mysql-server
在 Yum 更新完成之后, 启动MySQL,在 8.0.16 之后不需要执行 mysql_upgrade, 会自动处理。
以上处理完毕