溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

關(guān)于MYSQL flush table的作用

發(fā)布時(shí)間:2020-08-08 08:57:08 來(lái)源:ITPUB博客 閱讀:1091 作者:gaopengtttt 欄目:MySQL數(shù)據(jù)庫(kù)
關(guān)于MYSQL flush table的作用

水平有限,還待學(xué)習(xí)。如有錯(cuò)誤,請(qǐng)指正。

先給出官方文檔:
? 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.


描述說(shuō)的是FLUSH TABLE就是關(guān)閉打開(kāi)的表,并且刷新查詢(xún)緩存 ,如果有LOCK TABLES ... READ存在則不允許,
在如果需要同時(shí)進(jìn)行flush和實(shí)現(xiàn)READ LOCK 可以使用FLUSH TABLES tbl_name... WITH READ LOCK;




這里的關(guān)閉打開(kāi)的表,一定會(huì)讓會(huì)感到困惑,什么是打開(kāi)的表,
關(guān)閉打開(kāi)的表又是什么意思,同時(shí)關(guān)閉打開(kāi)的表需要同步臟數(shù)據(jù)到磁盤(pán)嗎?



    我們考慮使用innodb_file_per_table 方式建立的INNODB表每個(gè)表都有一個(gè)相應(yīng)的數(shù)據(jù)文件idb,格式文件frm
但是某些數(shù)據(jù)還是存儲(chǔ)在共享表空間。如果我們的線程要訪問(wèn)這個(gè)表的數(shù)據(jù)必須要首先打開(kāi)這些文件然后通過(guò)
pread()/read() lseek()等系統(tǒng)調(diào)用進(jìn)行文件位置尋找和讀取。那么我們打開(kāi)文件的系統(tǒng)調(diào)用應(yīng)該是open()系統(tǒng)調(diào)用。
     當(dāng)然這些必要要有一個(gè)LINUX系統(tǒng)及編程基礎(chǔ),先說(shuō)說(shuō)一個(gè)每個(gè)進(jìn)程都包含了PCB(PCB在內(nèi)核態(tài)空間,進(jìn)程間是共享的)
PCB是一個(gè)進(jìn)程存在的標(biāo)識(shí)存到了進(jìn)程運(yùn)行的相關(guān)信息,內(nèi)核中他實(shí)際上是一個(gè)結(jié)構(gòu)體,其中包含很多信息如我
們熟知的PID PPID(大約100多種信息)其中PCB中保存了一份文件描述符,我們很容易在內(nèi)核代碼task_struct
結(jié)構(gòu)體也就是PCB的信息中找到如下:
/* open file information */
        struct files_struct *files;
其對(duì)應(yīng)了內(nèi)核中的file結(jié)構(gòu)體,可以看到進(jìn)程有一個(gè)files_struct結(jié)構(gòu)體用于保存,我們可以簡(jiǎn)單認(rèn)為進(jìn)程進(jìn)行進(jìn)程保存
了一份打開(kāi)所有文件的文件描述符,這個(gè)文件描述符從0開(kāi)始向后計(jì)數(shù),每個(gè)計(jì)數(shù)表示打開(kāi)的一個(gè)文件。如果一個(gè)進(jìn)程要
打開(kāi)一個(gè)文件我們LINUX是使用的open()系統(tǒng)調(diào)用,這個(gè)函數(shù)成功放回的就是打開(kāi)的文件描述符,失敗則設(shè)置返回值為-1
同時(shí)給出perror,看看LINUX中對(duì)這個(gè)函數(shù)的解釋
open() and creat() return the new file descriptor, or -1 if an error occurred (in which case, errno 
is set appropriately).
      
     那么MYSQL既然是一個(gè)進(jìn)程多個(gè)線程,那么肯定也逃不掉這樣的LINUX安排,那么MYSQL既然要打開(kāi)表,那么底層的
調(diào)用必然是OPEN函數(shù),既然文件有打開(kāi)就有關(guān)閉,當(dāng)進(jìn)行LINUX系統(tǒng)編程或者C語(yǔ)言編程的時(shí)候,我們通常在使用完文件后
使用CLOSE()或者FCLOSE()來(lái)關(guān)閉文件,這樣系統(tǒng)釋放打開(kāi)文件所保留的file信息,防止內(nèi)存泄露。


    那么我們來(lái)證明一下使用strace 分別在LINUX進(jìn)程TRACE LINUX線程信息。




一、關(guān)于打開(kāi)表


1、首先關(guān)閉重啟mysql,避免其他的打開(kāi)的表的文件描述的干擾。
[root@hadoop1 kernels]# service mysqldefault restart
     Shutting down MySQL....                                    [  OK  ]
     Starting MySQL...                                          [  OK  ]
2、使用pstree查看mysql所有線程(先找到MYSQL進(jìn)程ID)
   mysqld(10735)─┬─{mysqld}(10745)
              ├─{mysqld}(10746)
              ...
              ├─{mysqld}(10773)
              └─{mysqld}(10774)
   我們新打開(kāi)一個(gè)MYSQL線程,
   [root@hadoop1 kernels]# pstree -p 10735
mysqld(10735)─┬─{mysqld}(10745)
              ├─{mysqld}(10746)
              ...
              ├─{mysqld}(10774)
              └─{mysqld}(10794)
   這樣我們找到我們新開(kāi)的會(huì)話的線程ID 10794.
3、對(duì)線程10794進(jìn)行STRACE
   strace -T -p 10794
   然后再新的會(huì)話打開(kāi)一個(gè)表,我這里打開(kāi)的是
   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>
......


我們來(lái)分析這里的關(guān)鍵步驟
open("./test/tstr.ibd", O_RDONLY)       = 39 <0.000332> 這里打開(kāi)表的文件tstr.ibd只讀方式,返回文件描述符39
lseek(39, 0, SEEK_END)                  = 98304 這個(gè)是放回當(dāng)前打開(kāi)文件的大小,也就是初始的96K,因?yàn)槲抑挥幸粭l數(shù)據(jù)
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>
這一行開(kāi)始真正的讀取數(shù)據(jù) 讀取了16384個(gè)字節(jié)。
close(39)                               = 0 <0.000243> 然后關(guān)閉了文件tstr.ibd
open("./test/tstr.ibd", O_RDWR)         = 39 <0.000015> 然后再次以讀寫(xiě)方式方式打開(kāi)了tstr.ibd 數(shù)據(jù)文件,返回文件描述符39
fcntl(39, F_SETLK, {type=F_WRLCK, whence=SEEK_SET, start=0, len=0}) = 0 <0.000015>
這一行設(shè)置了tstr.ibd文件的屬性,此函數(shù)用于改變文件屬性,為一需要寫(xiě)入鎖的屬性,并且開(kāi)始字節(jié)是0.


如果我們發(fā)現(xiàn)LINUX 在關(guān)閉文件后又一次以寫(xiě)鎖方式打開(kāi)了文件。我們現(xiàn)在來(lái)看看我們的線程中是否包含了這個(gè)文件描述符
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




二、關(guān)于FLUSH TABLE做了什么操作


1、在某些情況FLUSH TABLE 會(huì)被堵塞,如 LOCK TABLES ... READ
   其次我還得到表操作期間文件,比如DML期間(不是事物),表重構(gòu)期間,SELECT 讀取數(shù)據(jù)很慢
   一切不允許進(jìn)程關(guān)閉文件描述符的操作。
   比如alter table add key(DDL) 這個(gè)操作需要將索引系統(tǒng)保存到表空間數(shù)據(jù)文件。
   比如delete from(DML) 這個(gè)操作需要將數(shù)據(jù)從表空間數(shù)據(jù)文件刪除。
   比如SELECT 很慢期間 。
   
   
   其等待系統(tǒng)調(diào)用futex(0xbb3f35c, FUTEX_WAIT_PRIVATE, 1, {31535999, 999934000}
   
   
2、FLUSH 實(shí)際上做的操作為:


[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


我們來(lái)觀察這些操作全部是關(guān)閉文件描述符,但是我發(fā)現(xiàn)這里關(guān)閉的文件全部為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


同時(shí),會(huì)對(duì)
同步的數(shù)據(jù)進(jìn)行寫(xiě)到內(nèi)核緩沖區(qū)同時(shí)FSYNC此文件然后關(guān)閉。
但是對(duì)于INNODB數(shù)據(jù)文件,未發(fā)現(xiàn)關(guān)閉文件的情況。


那么我們可以視乎的得出2個(gè)結(jié)論


1、flush table 會(huì)關(guān)閉MYISAM和CSV(對(duì)其他存儲(chǔ)引擎作用未知)的文件描述符,同時(shí)會(huì)寫(xiě)臟數(shù)據(jù)到文件,同時(shí)關(guān)閉文件描述符,
   關(guān)閉文件。
2、flush table 在INNODB中不會(huì)真正的關(guān)閉文件描述符,同時(shí)也不會(huì)寫(xiě)臟數(shù)據(jù),但是FLUSH TABLE確實(shí)會(huì)由于
   innodb中對(duì)文件操作而造成堵塞,堵塞等待為futex系統(tǒng)調(diào)用。所以flush tbale對(duì)INNODB可能用處并不大。
   
   
水平有限,還待學(xué)習(xí)。如有錯(cuò)誤,請(qǐng)指正。


   
   
   
   
   






向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI