1. 問題
使用mysqldump備份數據時,有時會看到 show processlist 出現大量的 Waiting for table flush,mysqldump被卡住。而且可能會導致查詢也被卡住。
一個案例是執行備份:mysqldump -uroot -p --single-transaction --master-data=2 --set-gtid-purged=OFF testdb > /tmp/testdb.sql
然后show processlist:
當時立即把 mysqldump 的線程ctrl+c殺掉了。過一會兒 Waiting for table flush 狀態全部消失。這次是運氣好,沒有出現應用大面積的SQL被阻塞。mysql自己恢復了正常。之前遇到過一次,最后只能重啟了mysqld才解決。
所以 Waiting for table flush 也不可輕視,需要特別注意!!! 和 MDL:meta data lock 一樣需要特別注意。
2. 出現 Waiting for table flush的原因
https://dev.mysql.com/doc/refman/5.6/en/general-thread-states.html
The thread is executing FLUSH TABLES
and is waiting for all threads to close their tables, or the thread got a notification that the underlying structure for a table has changed and it needs to reopen the table to get the new structure. However, to reopen the table, it must wait until all other threads have closed the table in question.
This notification takes place if another thread has used FLUSH TABLES
or one of the following statements on the table in question: FLUSH TABLES
, tbl_name
ALTER TABLE
, RENAME TABLE
, REPAIR TABLE
, ANALYZE TABLE
, or OPTIMIZE TABLE
.
flush tables 語句需要或者 alter table,rename table,repair table,analyze table,optimize table 等DDL語句 需要關閉table,然后重新打開table,
而這些table可能會存在大的事務再執行,或者被鎖住了,從而無法關閉table,所以就出現了狀態:Waiting for table flush
也就是說:需要執行 flush tables 的線程,因為某些原因無法關閉表,無法完成flush tables,所以就 waiting for table flush.
3. 如何避免 mysqldump 導致的 Waiting for tables flush
--master-data[=#]
This causes the binary log position and filename to be appended to the output. If equal to 1, will print it as a CHANGE MASTER
command; if equal to 2, that command will be prefixed with a comment symbol. This option will turn --lock-all-tables on, unless
--single-transaction is specified too (in which case a global read lock is only taken a short time at the beginning of the dump;
don't forget to read about --single-transaction below). In all cases, any action on logs will happen at the exact moment of the dump.
Option automatically turns --lock-tables off.
mysqldump 的 --singel-transaction 和 --master-data選項一起用時:
1)需要執行 flush tables !!!!
2)需要執行 flush tables with read lock !!!
而這里的 flush tables 很可能被大事務、慢查詢 或者鎖給卡住了,從而導致了 Waiting for table flush !!!!
一般 --single-transacation和 --master-data 一起用時為了搭建主從復制。不然也一般不會使用 --master-data 選項。其實可以使用xtrabackup備份來做主從復制,不存在該問題。
所以為了避免 mysqldump 導致 Waiting for table flush 問題,需要避免 將 --single-transacation 和 --master-data 選項一起使用!最安全的方式是只使用 --single-transaction選項。
4. Waiting for table flush導致的問題
flush tables 無法完成會出現 waiting for table flush狀態,此時這個被 flush的表,即使是執行 select 語句也會被阻塞!!! 當然其他表還是可以正常的 select的。
5. Waiting for table flush 處理方法
出現Waiting for table flush時,我們一般需要找到那些表被lock住或那些慢查詢導致flush table一直在等待而無法關閉該表。然后Kill掉對應的線程即可,但是如何精准定位是一個挑戰,尤其是生產環境,你使用show processlist會看到大量的線程。讓你眼花繚亂的,怎么一下子定位問題呢?
對於慢查詢引起的其它線程處於Waiting for table flush狀態的情形:
可以查看show processlist中Time值很大的線程。然后甄別確認后Kill掉。有種規律就是這個線程的Time列值必定比被阻塞的線程要高。這個就能過濾很多記錄。
對於lock table read引起的其它線程處於Waiting for table flush狀態的情形:
這種會話可能處於Sleep狀態,而且它也不會出現在show engine innodb status \G命令的輸出信息中。 即使show open tables where in_use >=1;能找到是那張表被lock住了,但是無法定位到具體的線程(連接),其實這個是一個頭痛的問題。但是inntop這款利器就可以定位到,如下所示,線程17鎖住了表test,在innotop里面就能定位到是線程17。所謂工欲善其事必先利其器!
參考:https://www.cnblogs.com/kerrycode/p/7388968.html