前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >MySQL为什么lsof会看到这么多临时文件

MySQL为什么lsof会看到这么多临时文件

作者头像
老叶茶馆
发布2020-09-23 14:32:39
1.7K3
发布2020-09-23 14:32:39
举报

作者:高鹏(网名八怪),《深入理解MySQL主从原理32讲》系列的作者。

版本:5.7.29

一、问题提出

一般情况下我们会使用lsof命令来查看MySQL当前使用的临时文件的使用,这是因为这些临时文件使用ls命令并不能显示,在5.7中其建立方式是使用Liunx api mkstemp进行的建立,这种文件是进程专用的,返回文件描述符后会使用api unlink进行删除。

源码主要就是这一段,其包含在create_temp_file函数中。

    org_file=mkstemp(to);
    if (mode & O_TEMPORARY)
      (void) my_delete(to, MYF(MY_WME));

在5.7中如下常见的一些功能会用到这种临时文件,比如:

  • 执行计划 filesort 文件名字:MY开头
lsof|grep delete
如:/tmp/MYdRH1GW (deleted)
  • 大事务binary log缓存文件名字:ML开头
lsof|grep delete
如:/tmp/MLq9INFu (deleted)
  • online DDL 涉及排序比如add key,一般是 ib开头
alter table testsort add key(id);
lsof|grep delete
如:
/tmp/ibCxlYQg (deleted)
/tmp/ib51nvZ1 (deleted)
设置 innodb_tmpdir可以将这类文件放到指定的目录

但是当一个MySQLD进程刚刚启动的时候我们去查看这类文件的时候,会发现很多这类文件,如下:

[root@mgr2 ~]# lsof|grep delete|grep mysql|wc -l
215
[root@mgr2 ~]# 

这些文件大小基本都是0,且都以ib开头,曾经有朋友问过我这个问题,这里详细做一下解释。

二、MySQLD初始化后的临时文件种类

实际上在5.7中这类文件均由函数create_temp_file建立,那么我们就可以在MySQLD启动的时候将断点放在上面进行分析了。

下面这样一些文件,均使用的是ib开头的临时文件。

  • srv_monitor_file (srv0start.cc:2022):这是我们通常show engine innodb status命令输出的时候使用到的文件,主要函数为srv_printf_innodb_monitor。栈针:
  • srv_dict_tmpfile (srv0start.cc:2032):主要和外键创建信息输出有关。
  • srv_misc_tmpfile (srv0start.cc:2041):主要和外键抛错输出有关。
  • lock_latest_err_file (lock0lock.cc:465):主要和死锁报错输出有关。
  • dict_foreign_err_file (dict0dict.cc:1245):主要和外键抛错输出有关。

我们可以发现实际上这些文件都不会占用太大,实际上这5个文件初始化后就已经建立好了。

三、为什么lsof默认的输出会多很多

很明显我们上面ib打头的文件只有5个,那么我们lsof(不加任何参数)的时候看到的会多很多呢?

如下是我初始化启动的情况下看到的个数:

[root@mgr2 support-files]# lsof|grep delete|grep mysql|wc -l
215
[root@mgr2 support-files]# lsof|grep delete|grep mysql
mysqld    12916         mysql   10u      REG                8,5      9765   17109405 /tmp/ibpuzts2 (deleted)
mysqld    12916         mysql   11u      REG                8,5         0   23137683 /tmp/ibA4q9iX (deleted)
mysqld    12916         mysql   12u      REG                8,5         0   23137684 /tmp/ibRdXEl4 (deleted)
mysqld    12916         mysql   13u      REG                8,5         0   23137685 /tmp/ibe6hfHJ (deleted)
mysqld    12916         mysql   19u      REG                8,5         0   23137686 /tmp/ibfb7rps (deleted)
mysqld    12916 12920   mysql   10u      REG                8,5      9765   17109405 /tmp/ibpuzts2 (deleted)
mysqld    12916 12920   mysql   11u      REG                8,5         0   23137683 /tmp/ibA4q9iX (deleted)
mysqld    12916 12920   mysql   12u      REG                8,5         0   23137684 /tmp/ibRdXEl4 (deleted)
mysqld    12916 12920   mysql   13u      REG                8,5         0   23137685 /tmp/ibe6hfHJ (deleted)
mysqld    12916 12920   mysql   19u      REG                8,5         0   23137686 /tmp/ibfb7rps (deleted)
mysqld    12916 12944   mysql   10u      REG                8,5      9765   17109405 /tmp/ibpuzts2 (deleted)
mysqld    12916 12944   mysql   11u      REG                8,5         0   23137683 /tmp/ibA4q9iX (deleted)
mysqld    12916 12944   mysql   12u      REG                8,5         0   23137684 /tmp/ibRdXEl4 (deleted)
mysqld    12916 12944   mysql   13u      REG                8,5         0   23137685 /tmp/ibe6hfHJ (deleted)
mysqld    12916 12944   mysql   19u      REG                8,5         0   23137686 /tmp/ibfb7rps (deleted)
mysqld    12916 12945   mysql   10u      REG                8,5      9765   17109405 /tmp/ibpuzts2 (deleted)
mysqld    12916 12945   mysql   11u      REG                8,5         0   23137683 /tmp/ibA4q9iX (deleted)
mysqld    12916 12945   mysql   12u      REG                8,5         0   23137684 /tmp/ibRdXEl4 (deleted)
此处省略....

我们主要关注以下几列:

  • PID:is the Process IDentification number of the process.
  • TID:is the task (thread) IDentification number
  • FD:is the File Descriptor number of the file
  • SIZE/OFF:is the size of the file or the file offset in bytes
  • NAME:is the name of the mount point and file system on which the file resides 更加详细的自行参考man。

从输出中我们可以发现

  • PID都是12916这正是mysqld的PID,而它们的TID则不同,这些当然就是多线程造成的原因了。
  • FD和NAME实际上是有规律的重复的,其实只有5个值而已。这代表我们上面说的5个临时文件
  • SIZE都比较小。

因此我们可以认为虽然输出多达215行,但是实际上整个MySQLD进程只打开了5个文件而已也就是我们前面说的那5个临时文件,这是因为线程间文件描述符(FD)是共享的,每一个线程lsof查看的时候都会显示这5个临时文件,如果我们的MySQL有很多session,那么线程会很多很多,那么lsof看到的临时文件数量就是线程数据量*5。因此我们在检查临时文件使用空间情况的时候不要被过多的输出而吓到,我们只要输出MySQLD进程的临时文件即可,输出如下:

[root@mgr2 proc]# lsof|grep delete|grep mysql |awk '{if ($3=="mysql") print}' 
mysqld    12916         mysql   10u      REG                8,5      9765   17109405 /tmp/ibpuzts2 (deleted)
mysqld    12916         mysql   11u      REG                8,5         0   23137683 /tmp/ibA4q9iX (deleted)
mysqld    12916         mysql   12u      REG                8,5         0   23137684 /tmp/ibRdXEl4 (deleted)
mysqld    12916         mysql   13u      REG                8,5         0   23137685 /tmp/ibe6hfHJ (deleted)
mysqld    12916         mysql   19u      REG                8,5         0   23137686 /tmp/ibfb7rps (deleted)
或者加上lsof加上参数只看进程的临时文件,而不去查看子线程的临时文件
[root@mgr2 ~]#lsof -p 12916|grep delete
mysqld  12916 mysql   10u   REG                8,5      9765 17109405 /tmp/ibpuzts2 (deleted)
mysqld  12916 mysql   11u   REG                8,5         0 23137683 /tmp/ibA4q9iX (deleted)
mysqld  12916 mysql   12u   REG                8,5         0 23137684 /tmp/ibRdXEl4 (deleted)
mysqld  12916 mysql   13u   REG                8,5         0 23137685 /tmp/ibe6hfHJ (deleted)
mysqld  12916 mysql   19u   REG                8,5         0 23137686 /tmp/ibfb7rps (deleted)

注意MySQL8.0.21下这些临时文件的名字有一些变化,Liunx下可能直接(O_TMPFILE flag)使用这种方式建立如下:

open(dirname_buf, O_RDWR | O_TMPFILE | O_CLOEXEC,
                      S_IRUSR | S_IWUSR)
我测试得到的名字如下:
[root@mgr4 ~]# lsof|grep a.out|grep delete
a.out     11703          root    3u      REG                8,5         0   24237415 /tmp/#24237415 (deleted)
MySQLD启动后查看的临时文件名如下:
[root@mgr4 ~]# lsof -p 11488|grep delete
mysqld  11488 mysql   10u      REG                8,5         0 24237413 /tmp/#24237413 (deleted)
mysqld  11488 mysql   11u      REG                8,5         0 24237414 /tmp/#24237414 (deleted)
mysqld  11488 mysql   12u      REG                8,5         0 24237416 /tmp/#24237416 (deleted)
mysqld  11488 mysql   19u      REG                8,5         0 24237417 /tmp/#24237417 (deleted)

虽然临时文件名有所变化,但是基本的用途和5.7差不多

四、线程间的文件描述符(FD)是共享的

这一段没什么好解释的借用Linux系统编程的一段说明如下:

五、测试

我们可以写一段简单的多线程的代码来测试如下(不做任何错误判断):

#include<stdio.h>
#include<stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>

void* u_sleep(void* t)
{
  char file_temp[]="ibXXXXXX";
  int fd = mkstemp(file_temp);
  unlink( file_temp);
  int i = 0;
  char* teststr="aasd";
  printf("thead tmpfile: %s\n",file_temp);
  for(i = 0;i<100000;i++)
  {
    write(fd,teststr,strlen(teststr));
  }
  sleep(100);
}

int main(void)
{
   int ret = 0;
   pthread_t tid[5];
   int i = 0;
   int fd = 0;
   int tid_num = 0;
   int tmp_file_num=5;
   char file_temp[]="ibXXXXXX";
   for(i=0;i<tmp_file_num;i++)
   {
     strcpy(file_temp,"ibXXXXXX");
     mkstemp(file_temp);
     printf("%s\n",file_temp);
     unlink( file_temp);
   }
  for (i = 0;i<sizeof(tid)/sizeof(pthread_t);i++)
  {
    pthread_create(tid+tid_num,NULL,u_sleep,NULL);
    tid_num++;
  }
  for(i = 0;i<sizeof(tid)/sizeof(pthread_t);i++)
        {
                ret = pthread_join( *(tid+i) , NULL );
        }
}

这段代码实际上就是模拟在主进程中通过mkstemp和unlink建立了5个临时文件且也是以ib打头(模拟MySQL的临时文件),然后建立了5个线程,每个线程再各自建立一个临时文件,写点东西进去,然后线程睡眠一会,主线程会等待线程回收资源,因此可以有足够的时间观察到。

这样来观察是线程之间文件描述符(FD)是否共享,预期我们能够观察到的输出为60个(1个主控线程,5个子线程,主控线程建立了5个临时文件6个线程共享就是30个,然后每个子线程建立了1个临时文件又是5个临时文件,6个线程共享又是30个)如下输出:

[root@mgr2 ~]# lsof|grep delete|grep a.out|wc -l
60
[root@mgr2 ~]# lsof|grep delete|grep a.out|awk '{if ($3=="root") print}' 
a.out     13460          root    3u      REG                8,5         0   43691141 /root/ibpotqYK (deleted)
a.out     13460          root    4u      REG                8,5         0   43691142 /root/ibxlgopk (deleted)
a.out     13460          root    5u      REG                8,5         0   43691144 /root/ibHOmmQT (deleted)
a.out     13460          root    6u      REG                8,5         0   43691145 /root/ibvmykht (deleted)
a.out     13460          root    7u      REG                8,5         0   43691146 /root/ib3TViI2 (deleted)
a.out     13460          root    8u      REG                8,5    400000   43691147 /root/ibEn9hAb (deleted)
a.out     13460          root    9u      REG                8,5    400000   43691148 /root/ibkexi9B (deleted)
a.out     13460          root   10u      REG                8,5    400000   43691149 /root/ibJJZi1K (deleted)
a.out     13460          root   11u      REG                8,5    400000   43691150 /root/ibRRxKtk (deleted)
a.out     13460          root   12u      REG                8,5    400000   43691151 /root/ibWuKsWT (deleted)
[root@mgr2 ~]# lsof|grep delete|grep a.out|more
a.out     13460          root    3u      REG                8,5         0   43691141 /root/ibpotqYK (deleted)
a.out     13460          root    4u      REG                8,5         0   43691142 /root/ibxlgopk (deleted)
a.out     13460          root    5u      REG                8,5         0   43691144 /root/ibHOmmQT (deleted)
a.out     13460          root    6u      REG                8,5         0   43691145 /root/ibvmykht (deleted)
a.out     13460          root    7u      REG                8,5         0   43691146 /root/ib3TViI2 (deleted)
a.out     13460          root    8u      REG                8,5    400000   43691147 /root/ibEn9hAb (deleted)
a.out     13460          root    9u      REG                8,5    400000   43691148 /root/ibkexi9B (deleted)
a.out     13460          root   10u      REG                8,5    400000   43691149 /root/ibJJZi1K (deleted)
a.out     13460          root   11u      REG                8,5    400000   43691150 /root/ibRRxKtk (deleted)
a.out     13460          root   12u      REG                8,5    400000   43691151 /root/ibWuKsWT (deleted)
a.out     13460 13461    root    3u      REG                8,5         0   43691141 /root/ibpotqYK (deleted)
a.out     13460 13461    root    4u      REG                8,5         0   43691142 /root/ibxlgopk (deleted)
a.out     13460 13461    root    5u      REG                8,5         0   43691144 /root/ibHOmmQT (deleted)
a.out     13460 13461    root    6u      REG                8,5         0   43691145 /root/ibvmykht (deleted)
a.out     13460 13461    root    7u      REG                8,5         0   43691146 /root/ib3TViI2 (deleted)
a.out     13460 13461    root    8u      REG                8,5    400000   43691147 /root/ibEn9hAb (deleted)
a.out     13460 13461    root    9u      REG                8,5    400000   43691148 /root/ibkexi9B (deleted)
a.out     13460 13461    root   10u      REG                8,5    400000   43691149 /root/ibJJZi1K (deleted)
a.out     13460 13461    root   11u      REG                8,5    400000   43691150 /root/ibRRxKtk (deleted)
a.out     13460 13461    root   12u      REG                8,5    400000   43691151 /root/ibWuKsWT (deleted)
省略很多.....

因此我们的说法得到证明。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-09-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 老叶茶馆 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、问题提出
  • 二、MySQLD初始化后的临时文件种类
  • 三、为什么lsof默认的输出会多很多
  • 四、线程间的文件描述符(FD)是共享的
  • 五、测试
相关产品与服务
云数据库 SQL Server
腾讯云数据库 SQL Server (TencentDB for SQL Server)是业界最常用的商用数据库之一,对基于 Windows 架构的应用程序具有完美的支持。TencentDB for SQL Server 拥有微软正版授权,可持续为用户提供最新的功能,避免未授权使用软件的风险。具有即开即用、稳定可靠、安全运行、弹性扩缩等特点。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档