MySQL why lsof sees so many temporary files

Author: Gao Peng (screen name eight strange), "in-depth understanding of the principles of MySQL master From 32" series author.
Series link: https://www.jianshu.com/nb/43148932

Version: 5.7.29

1. Questions raised

Under normal circumstances, we will use the lsof command to view the use of temporary files currently used by MySQL. This is because these temporary files cannot be displayed using the ls command. In 5.7, the method of creation is to use Liunx api mkstemp to create this file. It is process-specific. After returning the file descriptor, it will be deleted using api unlink.

The source code is mainly this section, which is contained in the create_temp_file function.

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

Some of the following common functions in 5.7 will use this kind of temporary files, such as:

  • Execution plan filesort file name: beginning with MY

lsof|grep delete
如:/tmp/MYdRH1GW (deleted)

  • Big transaction binary log cache file name: ML beginning

lsof|grep delete
如:/tmp/MLq9INFu (deleted)

  • Online DDL involves sorting such as add key, which usually starts with ib

alter table testsort add key(id);
lsof|grep delete
如:
/tmp/ibCxlYQg (deleted)
/tmp/ib51nvZ1 (deleted)
设置 innodb_tmpdir可以将这类文件放到指定的目录

But when we check this kind of file when a MySQLD process just started, we will find many such files, as follows:

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

The size of these files are basically 0, and they all start with ib. A friend once asked me this question. Here is a detailed explanation.

2. Types of temporary files after MySQLD initialization

In fact, in 5.7 such files are created by the function create_temp_file, then we can put a breakpoint on it for analysis when MySQLD starts.

The following files are temporary files beginning with ib.

  • srv_monitor_file (srv0start.cc:2022): This is the file we usually use when outputting the show engine innodb status command. The main function is srv_printf_innodb_monitor. Stack pin:

  • srv_dict_tmpfile (srv0start.cc:2032): Mainly related to the output of foreign key creation information.

  • srv_misc_tmpfile (srv0start.cc:2041): Mainly related to foreign key throwing error output.

  • lock_latest_err_file (lock0lock.cc:465): Mainly related to deadlock error output.

  • dict_foreign_err_file (dict0dict.cc:1245): mainly related to foreign key throwing error output.

We can find that in fact, these files will not occupy too much. In fact, these 5 files have been created after initialization.

Three, why the default output of lsof is much more

Obviously we only have 5 files starting with ib above, so what do we see when we lsof (without any parameters)?

The following is the number I see when I initialize it:

[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)
此处省略....

We mainly focus on the following columns:

  • 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 Refer to man for more details.

From the output we can find

  • The PIDs are all 12916. This is the PID of mysqld, but their TIDs are different. These are of course the cause of multithreading.

  • FD and NAME are actually repeated regularly, in fact there are only 5 values. This represents the 5 temporary files we mentioned above

  • SIZE is relatively small.

Therefore, we can think that although the output is up to 215 lines, in fact the entire MySQLD process only opens 5 files, which is the 5 temporary files we mentioned earlier, because the file descriptor (FD) is shared between threads , Every thread lsof will display these 5 temporary files when viewing it. If our MySQL has a lot of sessions, then there will be a lot of threads, so the number of temporary files seen by lsof is the amount of thread data*5. Therefore, when checking the space usage of temporary files, do not be surprised by excessive output. We only need to output the temporary files of the MySQLD process. The output is as follows:

[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)


Note that there are some changes in the names of these temporary files under MySQL8.0.21, and they may be created directly (O_TMPFILE flag) in this way under Linx as follows:

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)


Although the temporary file name has changed, the basic purpose is similar to 5.7

Fourth, the file descriptor (FD) between threads is shared

This paragraph borrows Linux system programming and explains it as follows:

Five, test

We can write a simple multi-threaded code to test as follows (without making any wrong judgments):

#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 );
        }
}

This code actually simulates the establishment of 5 temporary files through mkstemp and unlink in the main process and also starts with ib (simulating MySQL temporary files), and then establishes 5 threads, and each thread creates a temporary file. , Write something in, and then the thread sleeps for a while, the main thread will wait for the thread to reclaim resources, so you can have enough time to observe.

In this way, the observation is whether the file descriptor (FD) is shared between threads. It is expected that the output we can observe is 60 (1 main control thread, 5 child threads, the main control thread establishes 5 temporary files and 6 threads share That is 30, and then each sub-thread creates 1 temporary file and 5 temporary files, and 6 threads share 30 again) The following output:

[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)
省略很多.....

So our statement is proved.

Scan code to add author WeChat

The full text is over.

Enjoy MySQL :)

Teacher Ye's "MySQL Core Optimization" class has been upgraded to MySQL 8.0, scan the code to start the journey of MySQL 8.0 practice

Guess you like

Origin blog.csdn.net/n88Lpo/article/details/108590890