xtrabackup相信目前使用已經非常廣泛了,備份innodb表的首選工具,但是其中還是有點小坑,雖然發生的概率不大,但是我還是踩坑了。關於xtrabackup的詳細參考請查閱官方文檔http://www.percona.com/doc/percona-xtrabackup/2.2/intro.html
突然收到報警,說從庫延時,登錄服務器執行show full processlist查看,發現有如下狀態(自己模擬的,和當時線上情況一樣):
可以看見這里的INSERT語句卡住了,在等待一個全局鎖,所以導致從庫延時。那么問題來了。。。。。為什么有一個全局鎖,FLUSH TABLES WITH READ LOCK。后來發現是剛不久在從庫加了一個備份腳本,備份工具采用的是Percona的xtrabackup工具。這個工具在拷貝完文件以后需要執行FLUSH TABLES WITH READ LOCK。如下圖:
由於需要執行FLUSH TABLES WITH READ LOCK (以下用FTWRL縮寫代替)來獲取全局GLOBAL的MDL鎖,因此可以看到"wait for global read lock"之類的信息。如果備庫存在大查詢,或者復制線程正在執行比較漫長的DDL,並且FTWRL被block住,那么隨后的QUERY都會被block住,導致業務不可用引發故障。
剛好在percona博客看到一篇文章,里面大概是這樣說FTWRL。
What’s the problem with FTWRL anyway?
A lot has been written on what FLUSH TABLES WITH READ LOCK
really does. Here’s yet another walk-through in a bit more detail than described elsewhere:
- It first invalidates the Query Cache.
- It then waits for all in-flight updates to complete and at the same time it blocks all incoming updates. This is one problem for busy servers.
- It then closes all open tables (the
FLUSH
part) and expels them from the table cache. This is also whenFTWRL
has to wait for allSELECT
queries to complete. And this is another, even bigger problem for busy servers, because that wait happens to occur with all updates blocked. What’s even worse, the server at this stage is essentially offline, because even incomingSELECT
queries will get blocked. - Finally, it blocks COMMITs.
1.它首先使查詢緩存無效。
2.然后,等待所有更新完成,並在同一時間,它阻止所有的更新。這對於繁忙的服務器是一個問題。
3.然后,它關閉所有打開的表(沖洗表)並且從表中的高速緩存刷出。這也是當FTWRL必須等待所有的SELECT查詢完成。這是另一個更大的問題為繁忙的服務器,因為等待恰好發生這將堵塞所有的更新。更糟的是,服務器在這個階段基本上是離線狀態,因為即使進入的SELECT查詢將被封鎖。
4.最后,它會阻止事務提交。
Percona已經提供了解決方案(2.1版本開始):
設置一個超時時間,避免無限期的等待。Xtrabackup提供了以下參數實現該功能:
--lock-wait-timeout=SECONDS, ,一旦Flush table with read lock被阻塞超過預定時間,則XtraBackup出錯返回退出,該值默認為0,也就是說一旦阻塞,立即返回失敗。
--lock-wait-query-type=all|update,該參數允許用戶指定,哪類的SQL語句是需要Flush table with read lock等待的,同時用戶可以通過--lock-wait-threshold=SECONDS設置等待的時間,如果不在query-type指定的類型范圍內或者超過了wait-threshold指定的時間,XtraBackup均返回錯誤。如果指定update類型,則UPDATE/ALTER/REPLACE/INSERT 均會等待,ALL表示所有的SQL語句。
kill 其他阻塞線程
Kill掉所有阻塞Flush table with read lock的線程:
--kill-long-queries-timeout=SECONDS參數允許用戶指定了超過該閾值時間的查詢會被Kill,同時也允許用戶指定Kill
SQL語句的類型。
--kill-long-query-type=all|select
默認值為ALL,如果選擇Select,只有Select語句會被Kill,如果Flush table with read lock是被Update語句阻塞,則XtraBackup不會處理。
總結:
本次的復制延時故障由於從庫在執行大查詢,而且效率很差,剛好備份腳本執行,由於xtrabackup執行FLUSH TABLES WITH READ LOCK施加全局鎖,導致鎖等待。這時剛好從庫執行INSERT操作,最后導致無法插入,等待全局鎖,導致復制延時。
參考資料
http://m.csdn.net/article/2015-01-20/2823634
http://www.percona.com/blog/2014/03/11/introducing-backup-locks-percona-server-2/
http://www.percona.com/blog/2010/04/24/how-fast-is-flush-tables-with-read-lock/
http://www.percona.com/doc/percona-xtrabackup/2.2/innobackupex/improved_ftwrl.html