為什么要使用FTWRL
MySQL dba在日常工作中,數據備份絕對是工作頻度最高的工作內容之一。當你使用邏輯方式進行備份(mydumper,mysqldump)或物理方式進行備份(percona-xtrabackup),為了保證數據的一致性,這兩種備份方式都會在備份過程中執行 flush table with read lock 這個命令(**以下簡稱為FTWRL**
),通過執行FTWRL,來對事務和非事務表來加table level級別的共享鎖,取得此時的gtid或者binlog偏移量,繼而得到某一個時間點的備份數據。
FTWRL是如何工作的
在過去的很長一段時間內,我們做備份一直是按以上的方式來做的,那么這種依靠FTWRL這種方式獲得備份點的做法是否真的合理,對數據庫有什么不良的影響嗎?
首先讓我們來看下,FTWRL具體做了哪些事情,當flush tables with read lock這條命令在數據庫中被執行的時候,執行邏輯可以分為下面的幾個步驟:
步驟一、請求獲得相關類型的 MDL lock,這里我們暫時稱之為 FTWRL_MDL_LOCK. 步驟二、清空query cache中的內容(當前應該很少有人開啟這個功能了) 步驟三、FLUSH TABLES,將當前所有打開的table的fd關閉 步驟四、請求獲得全局table-level lock
步驟五、上全局COMMIT鎖(make_global_read_lock_block_commit)
以上步驟,在某些db場景下會產生非常嚴重的問題,我們以下面栗子說明:
當有很大的事務在進行的時候,此時FTWRL的步驟一,步驟二可以完成,但是進行到步驟三的時候,由於表相關的事務正在執行中,相應table的句柄被占用,無法進行flush table操作。
筆者當時在現網就遇到這種情景,當時使用的工具是mydumper,該工具在進行到FTWRL步驟的時候,在步驟三卡住了,此時工具hang在那里,但是還誤以為加鎖失敗,自然對業務不會造成影響,實際上步驟一,步驟二已經成功執行了,要命的是步驟一的FTWRL_MDL_LOCK對DML事務的排他的,所以在工具hang住的期間,其他的后續DML事務都是被阻塞的 -_-
有比FTWRL更好的方法嗎
我們發現FTWRL是一種非常重量級鎖,或者說采取了一些額外過度的動作。有非常大的可能失敗,比如非常大的事務正在執行,這時候會被阻塞;而阻塞的時候又會影響其他的DML事務的執行,這時候是很危險的!
那是否有改良的更好方案呢,percona的回答的是肯定的,在 5.6.16-64.0這個版本中,percona開始引入了兩個新的MDL類型的鎖,相應的引入了兩個新的備份命令
> LOCK TABLES FOR BACKUP > LOCK BINLOG FOR BACKUP
lock tables for backup
執行該命令后,獲得的新的MDL鎖會阻塞對非事務表的更新及所有DDL動作,此時其他用戶可以繼續更新inonodb引擎的表,但是無法對myisam表進行更新動作。
lock binglog for backup
執行該命令后,如果加鎖成功,將會阻塞binglog的更新,此時所有的DML操作被阻塞。
那么通過上面兩個命令在獲取一致性的數據備份相比之前用FTWRL,有什么好處呢,我們通過下面兩張圖可以看到區別:
首先我們看下在非percona-5.6.16-64.0版本中。xtrabackup的工作流程:
然后我們看下percona-5.6.16-64.0版本及以上中,xtrabackup備份的流程是怎樣的:
從上面兩張圖我們可以總結如下:
1、使用FTWTRL備份的方式,如果myisam表數量眾多,或者當前有大事務在執行,FTWTRL處於等待或者FTWTRL保持,這個時間段期間,后續對innod的DML都將被阻塞,因此時間持續越長,對業務影響越大。
2、使用 lock tables for backup備份myisam表期間,對innodb的dml事務無影響,且加鎖過程不受當前是否有大事務正在執行的影響
我們可以發現使用 lock table和lock binlog來備份數據,不僅可以實現更輕量級的上鎖,並且可以節約myisam備份期間對業務的寫操作影響,我在percona server的環境下試驗證了以下,可以看到xtrabackup不再使用FTWRL命令了
percona這個小的改動解決了之前長期以來熱備數據的問題,特別是非percona server 版本下的雲平用戶有的執着使用myisam引擎,在備份期間非常容易造成監控程序的寫入失敗,從而觸發告警,-_-。