關於MYSQL flush table的作用

gaopengtttt發表於2016-02-28
關於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可能用處並不大。
   
   
水平有限,還待學習。如有錯誤,請指正。


   
   
   
   
   






來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/7728585/viewspace-2006227/,如需轉載,請註明出處,否則將追究法律責任。

相關文章