关于MYSQL flush table的作用

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 关于MYSQL flush table的作用水平有限,还待学习。如有错误,请指正。 先给出官方文档: ? FLUSH TABLES Closes all open tables, forces all tables in use to be closed, and flushes the query cache.
关于MYSQL flush table的作用

水平有限,还待学习。如有错误,请指正。

先给出官方文档:
? FLUSH TABLES
Closes all open tables, forces all tables in use to be closed, and flushes the query cache. FLUSH
TABLES also removes all query results from the query cache, like the RESET QUERY CACHE
statement.
In MySQL 5.6, FLUSH TABLES is not permitted when there is an active LOCK TABLES ... READ.
To flush and lock tables, use FLUSH TABLES tbl_name... WITH READ LOCK instead.
? FLUSH TABLES tbl_name[, tbl_name] ...
With a list of one or more comma-separated table names, this statement is like FLUSH TABLES with
no names except that the server flushes only the named tables. No error occurs if a named table
does not exist.


描述说的是FLUSH TABLE就是关闭打开的表,并且刷新查询缓存 ,如果有LOCK TABLES ... READ存在则不允许,
在如果需要同时进行flush和实现READ LOCK 可以使用FLUSH TABLES tbl_name... WITH READ LOCK;




这里的关闭打开的表,一定会让会感到困惑,什么是打开的表,
关闭打开的表又是什么意思,同时关闭打开的表需要同步脏数据到磁盘吗?



    我们考虑使用innodb_file_per_table 方式建立的INNODB表每个表都有一个相应的数据文件idb,格式文件frm
但是某些数据还是存储在共享表空间。如果我们的线程要访问这个表的数据必须要首先打开这些文件然后通过
pread()/read() lseek()等系统调用进行文件位置寻找和读取。那么我们打开文件的系统调用应该是open()系统调用。
     当然这些必要要有一个LINUX系统及编程基础,先说说一个每个进程都包含了PCB(PCB在内核态空间,进程间是共享的)
PCB是一个进程存在的标识存到了进程运行的相关信息,内核中他实际上是一个结构体,其中包含很多信息如我
们熟知的PID PPID(大约100多种信息)其中PCB中保存了一份文件描述符,我们很容易在内核代码task_struct
结构体也就是PCB的信息中找到如下:
/* open file information */
        struct files_struct *files;
其对应了内核中的file结构体,可以看到进程有一个files_struct结构体用于保存,我们可以简单认为进程进行进程保存
了一份打开所有文件的文件描述符,这个文件描述符从0开始向后计数,每个计数表示打开的一个文件。如果一个进程要
打开一个文件我们LINUX是使用的open()系统调用,这个函数成功放回的就是打开的文件描述符,失败则设置返回值为-1
同时给出perror,看看LINUX中对这个函数的解释
open() and creat() return the new file descriptor, or -1 if an error occurred (in which case, errno 
is set appropriately).
      
     那么MYSQL既然是一个进程多个线程,那么肯定也逃不掉这样的LINUX安排,那么MYSQL既然要打开表,那么底层的
调用必然是OPEN函数,既然文件有打开就有关闭,当进行LINUX系统编程或者C语言编程的时候,我们通常在使用完文件后
使用CLOSE()或者FCLOSE()来关闭文件,这样系统释放打开文件所保留的file信息,防止内存泄露。


    那么我们来证明一下使用strace 分别在LINUX进程TRACE LINUX线程信息。




一、关于打开表


1、首先关闭重启mysql,避免其他的打开的表的文件描述的干扰。
[root@hadoop1 kernels]# service mysqldefault restart
     Shutting down MySQL....                                    [  OK  ]
     Starting MySQL...                                          [  OK  ]
2、使用pstree查看mysql所有线程(先找到MYSQL进程ID)
   mysqld(10735)─┬─{mysqld}(10745)
              ├─{mysqld}(10746)
              ...
              ├─{mysqld}(10773)
              └─{mysqld}(10774)
   我们新打开一个MYSQL线程,
   [root@hadoop1 kernels]# pstree -p 10735
mysqld(10735)─┬─{mysqld}(10745)
              ├─{mysqld}(10746)
              ...
              ├─{mysqld}(10774)
              └─{mysqld}(10794)
   这样我们找到我们新开的会话的线程ID 10794.
3、对线程10794进行STRACE
   strace -T -p 10794
   然后再新的会话打开一个表,我这里打开的是
   select count(*) from tstr;
   
   
   Process 10794 attached - interrupt to quit
......
open("./test/tstr.ibd", O_RDONLY)       = 39 <0.000332>
getcwd("/mysql/data"..., 4096)          = 12 <0.000118>
lstat("/mysql/data/test", {st_mode=S_IFDIR|0700, st_size=4096, ...}) = 0 <0.000114>
lseek(39, 0, SEEK_END)                  = 98304 <0.000109>
pread(39, "*z\322_\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\313\332\7\342\0\10\0\0\0\0\0\0"..., 16384, 0) = 16384 <0.016728>
close(39)                               = 0 <0.000243>
open("./test/tstr.ibd", O_RDWR)         = 39 <0.000015>
fcntl(39, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0 <0.000015>
......


我们来分析这里的关键步骤
open("./test/tstr.ibd", O_RDONLY)       = 39 <0.000332> 这里打开表的文件tstr.ibd只读方式,返回文件描述符39
lseek(39, 0, SEEK_END)                  = 98304 这个是放回当前打开文件的大小,也就是初始的96K,因为我只有一条数据
pread(39, "*z\322_\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\313\332\7\342\0\10\0\0\0\0\0\0"..., 16384, 0) = 16384 <0.016728>
这一行开始真正的读取数据 读取了16384个字节。
close(39)                               = 0 <0.000243> 然后关闭了文件tstr.ibd
open("./test/tstr.ibd", O_RDWR)         = 39 <0.000015> 然后再次以读写方式方式打开了tstr.ibd 数据文件,返回文件描述符39
fcntl(39, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0 <0.000015>
这一行设置了tstr.ibd文件的属性,此函数用于改变文件属性,为一需要写入锁的属性,并且开始字节是0.


如果我们发现LINUX 在关闭文件后又一次以写锁方式打开了文件。我们现在来看看我们的线程中是否包含了这个文件描述符
4、


[root@hadoop1 fd]# pwd
/proc/10794/fd
[root@hadoop1 fd]# ls -lrt|grep tstr.ibd
lrwx------ 1 root root 64 Dec  5 06:36 39 -> /mysql/data/test/tstr.ibd




二、关于FLUSH TABLE做了什么操作


1、在某些情况FLUSH TABLE 会被堵塞,如 LOCK TABLES ... READ
   其次我还得到表操作期间文件,比如DML期间(不是事物),表重构期间,SELECT 读取数据很慢
   一切不允许进程关闭文件描述符的操作。
   比如alter table add key(DDL) 这个操作需要将索引系统保存到表空间数据文件。
   比如delete from(DML) 这个操作需要将数据从表空间数据文件删除。
   比如SELECT 很慢期间 。
   
   
   其等待系统调用futex(0xbb3f35c, FUTEX_WAIT_PRIVATE, 1, {31535999, 999934000}
   
   
2、FLUSH 实际上做的操作为:


[root@hadoop1 fd]# strace -T -p 15101
Process 15101 attached - interrupt to quit
....
close(24)                               = 0 <0.000115>
close(25)                               = 0 <0.000108>
close(28)                               = 0 <0.000099>
close(29)                               = 0 <0.000097>
close(26)                               = 0 <0.000242>
close(27)                               = 0 <0.000008>
close(30)                               = 0 <0.000008>
close(31)                               = 0 <0.000007>
close(32)                               = 0 <0.000007>
close(33)                               = 0 <0.000007>
close(22)                               = 0 <0.000152>
close(23)                               = 0 <0.000147>
close(20)                               = 0 <0.000110>
close(21)                               = 0 <0.000376>
close(34)                               = 0 <0.000008>
close(35)                               = 0 <0.000007>
close(38)                               = 0 <0.000008>
lseek(37, 0, SEEK_SET)                  = 0 <0.000011>
write(37, "\376\1\354:\1\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 35) = 35 <0.000025>
fsync(37)                               = 0 <0.008020>
close(37)                               = 0 <0.000071>
close(39)                               = 0 <0.000061>
...
Process 15101 detached


我们来观察这些操作全部是关闭文件描述符,但是我发现这里关闭的文件全部为MYISAM的和CSV文件,如下:
lrwx------ 1 root root 64 Dec  5 08:27 4 -> /mysql/data/test/ibdata1
lrwx------ 1 root root 64 Dec  5 08:27 39 -> /mysql/data/mysql/general_log.CSV
lr-x------ 1 root root 64 Dec  5 08:27 38 -> /mysql/data/mysql/general_log.CSV
lrwx------ 1 root root 64 Dec  5 08:27 37 -> /mysql/data/mysql/general_log.CSM
lrwx------ 1 root root 64 Dec  5 08:27 36 -> socket:[42669]
lrwx------ 1 root root 64 Dec  5 08:27 35 -> /mysql/data/mysql/event.MYD
lrwx------ 1 root root 64 Dec  5 08:27 34 -> /mysql/data/mysql/event.MYI
lrwx------ 1 root root 64 Dec  5 08:27 33 -> /mysql/data/mysql/servers.MYD
lrwx------ 1 root root 64 Dec  5 08:27 32 -> /mysql/data/mysql/servers.MYI
lrwx------ 1 root root 64 Dec  5 08:27 31 -> /mysql/data/mysql/procs_priv.MYD
lrwx------ 1 root root 64 Dec  5 08:27 30 -> /mysql/data/mysql/procs_priv.MYI
lrwx------ 1 root root 64 Dec  5 08:27 3 -> /mysql/data/binlog.index
lrwx------ 1 root root 64 Dec  5 08:27 29 -> /mysql/data/mysql/columns_priv.MYD
lrwx------ 1 root root 64 Dec  5 08:27 28 -> /mysql/data/mysql/columns_priv.MYI
lrwx------ 1 root root 64 Dec  5 08:27 27 -> /mysql/data/mysql/tables_priv.MYD
lrwx------ 1 root root 64 Dec  5 08:27 26 -> /mysql/data/mysql/tables_priv.MYI
lrwx------ 1 root root 64 Dec  5 08:27 25 -> /mysql/data/mysql/proxies_priv.MYD
lrwx------ 1 root root 64 Dec  5 08:27 24 -> /mysql/data/mysql/proxies_priv.MYI
lrwx------ 1 root root 64 Dec  5 08:27 23 -> /mysql/data/mysql/db.MYD
lrwx------ 1 root root 64 Dec  5 08:27 22 -> /mysql/data/mysql/db.MYI
lrwx------ 1 root root 64 Dec  5 08:27 21 -> /mysql/data/mysql/user.MYD
lrwx------ 1 root root 64 Dec  5 08:27 20 -> /mysql/data/mysql/user.MYI


同时,会对
同步的数据进行写到内核缓冲区同时FSYNC此文件然后关闭。
但是对于INNODB数据文件,未发现关闭文件的情况。


那么我们可以视乎的得出2个结论


1、flush table 会关闭MYISAM和CSV(对其他存储引擎作用未知)的文件描述符,同时会写脏数据到文件,同时关闭文件描述符,
   关闭文件。
2、flush table 在INNODB中不会真正的关闭文件描述符,同时也不会写脏数据,但是FLUSH TABLE确实会由于
   innodb中对文件操作而造成堵塞,堵塞等待为futex系统调用。所以flush tbale对INNODB可能用处并不大。
   
   
水平有限,还待学习。如有错误,请指正。


   
   
   
   
   






相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
7月前
|
存储 关系型数据库 MySQL
在阿里云的AnalyticDB MySQL版中使用CREATE TABLE语句来创建内表
在阿里云的AnalyticDB MySQL版中使用CREATE TABLE语句来创建内表【1月更文挑战第16天】【1月更文挑战第78篇】
368 3
|
Oracle 关系型数据库 MySQL
MySQL复制表结构create table as与like的区别
MySQL复制表结构create table as与like的区别
135 0
|
SQL Oracle 关系型数据库
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
【MySQL异常】1093 - You can‘t specify target table ‘daily_job‘ for update in FROM clause
245 0
|
7月前
|
存储 关系型数据库 MySQL
MySQL技能完整学习列表5、数据库操作——1、创建数据库和表——2、修改表结构(ALTER TABLE)
MySQL技能完整学习列表5、数据库操作——1、创建数据库和表——2、修改表结构(ALTER TABLE)
236 0
|
7月前
|
关系型数据库 MySQL
MySQL 报错 [ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file
MySQL 报错 [ERROR] [FATAL] InnoDB: Table flags are 0 in the data dictionary but the flags in file
959 0
|
关系型数据库 MySQL 数据库
对于mysql数据库delect from,truncate table,drop table, update操作的时候如何选择
对于mysql数据库delect from,truncate table,drop table, update操作的时候如何选择
237 2
|
3月前
|
SQL 关系型数据库 MySQL
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
MySQL 8.0报错--1118-Row size too large. The maximum row size for the used table type, not counting BLOBs,is 8126,
|
SQL 存储 关系型数据库
MySQL创建数据表(CREATE TABLE语句)
MySQL创建数据表(CREATE TABLE语句)
1011 0
|
2月前
|
SQL 关系型数据库 MySQL
MySQL异常一之: You can‘t specify target table for update in FROM clause解决办法
这篇文章介绍了如何解决MySQL中“不能在FROM子句中指定更新的目标表”(You can't specify target table for update in FROM clause)的错误,提供了错误描述、需求说明、错误做法和正确的SQL写法。
661 0
|
6月前
|
关系型数据库 MySQL 数据库
【MySQL】MySQL数据库的delete from table和truncate table之间的区别
【MySQL】MySQL数据库的delete from table和truncate table之间的区别
719 1