mysqldump與innobackupex備份過程你知多少(完結篇)

沃趣科技發表於2017-07-17
沃趣科技  羅小波

現在看innobackupex


2.1. innobackupex備份過程解讀


A庫清空查詢日誌

mysqldump與innobackupex備份過程你知多少(完結篇)

為了更清晰地追蹤innobackupex是如何拷貝redo log的,我們在A庫新開一個ssh會話2,使用如下指令碼持續對錶t_luoxiaobo進行插入操作(該表為innodb表),限於篇幅,請到如下為知筆記連結獲取

  • http://5d096a11.wiz03.com/share/s/1t2mEh0a-kl_2c2NZ33kSiac1Rgvxq1vgkhL21ibWU2cLidk

A庫使用innobackupex執行備份,使用strace命令抓取備份過程中的呼叫棧

mysqldump與innobackupex備份過程你知多少(完結篇)

檢視general_log日誌中的記錄(刪掉了加壓指令碼中的語句)

mysqldump與innobackupex備份過程你知多少(完結篇)

從上面的記錄中可以看到,與mysqldump相比,innobackupex備份時對資料庫的操作多了一個FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS,稍後對這句的作用進行解釋

因為innobackupex是物理拷貝檔案,資料並不像mysqldump那樣通過對資料庫表執行select語句查詢進行備份,而是通過拷貝磁碟檔案進行備份的,所以,主體的備份流程還需要看strace的呼叫棧,限於篇幅原因,詳見為知筆記外鏈:http://5d096a11.wiz03.com/share/s/1t2mEh0a-kl_2c2NZ33kSiac2ZRJlK3qIAQr2LjYMx2xMkCD

通過備份輸出日誌和strace呼叫棧,整理的流程圖如下(全備) :

mysqldump與innobackupex備份過程你知多少(完結篇)


2.2. innobackupex為什麼需要這麼做


nnobackupex備份時啟動一個程式多個執行緒,通過拷貝磁碟檔案實現物理備份,為了保證備份資料的一致性,需要在備份過程中恰當的時機傳送一些加鎖解鎖語句與資料庫例項進行互動,so…要了解innobackupex工具的整個備份過程中做了哪些事情,我們就需要檢視general_log和備份過程中的日誌輸出(其實strace呼叫棧資訊裡就可以瞭解到innobackupex所做的所有事情,但是。。都是系統呼叫,看起來比較費勁),對於備份過程中的日誌輸出,這裡就不再熬述,詳見上文中的"全備流程圖",本小節我們只介紹general_log中的輸出重點語句,如下:

  • FLUSH NO_WRITE_TO_BINLOG TABLES、FLUSH TABLES WITH READ LOCK、SHOW MASTER STATUS、UNLOCK TABLES幾個語句的作用與mysqldump備份過程中的這幾個語句的作用一樣

  • FLUSH NO_WRITE_TO_BINLOG ENGINE LOGS,該語句在mysqldump備份過程中沒有 
    * 這句的作用是在所有的事務表和非事務表備份完成,獲取了全域性讀鎖,且使用SHOW MASTER STATUS語句獲取了binlog pos之後,執行重新整理redo log buffer中的日誌到磁碟中,然後redo log copy執行緒拷貝這最後的redo log日誌資料(為什麼說是最後的redo log日誌資料呢?因為此時使用FLUSH TABLES WITH READ LOCK加鎖之後,使用UNLOCK TABLES釋放全域性讀鎖之前,不會再有新的請求進來,),拷貝完成之後就停止copy執行緒並關閉xtrabackup_logfile檔案。然後再使用UNLOCK TABLES釋放全域性讀鎖。 
    * 詳見姜承堯老師的推文:http://chuansong.me/n/372118651979


2.3. innobackupex有什麼坑嗎?


從上文中介紹的innobackupex的備份流程和原理上,我們可以得知,innobackupex工具備份過程中是不會出現前面提到的mysqldump備份工具的"坑一"的。因為innobackupex備份工具是在所有事務表和非事務表都備份完成之後才會執行UNLOCK TABLES釋放全域性讀鎖,so…從加鎖之後,解鎖之前不可能有任何其他的DML請求能夠對資料做修改,從而保證的備份資料的一致性。

那麼,mysqldump的"坑二"呢?我們來看下面請看演示過程

A庫使用如下指令碼持續對錶t_luoxiaobo進行插入操作(該表為innodb表),限於篇幅,請到如下為知筆記連結獲取(留意把program_name變數值改為"innobackupex")

http://5d096a11.wiz03.com/share/s/1t2mEh0a-kl_2c2NZ33kSiac1Rgvxq1vgkhL21ibWU2cLidk

A庫新開一個ssh會話2,執行innobackupex備份,留意日誌列印過程。從下面的結果中,我們可以看到報錯終止了:

mysqldump與innobackupex備份過程你知多少(完結篇)

發生什麼了?

  • 首先,我們知道,innobackupex在備份事務表時,是沒有對資料庫加鎖的,so..這個時候,其實DDL是允許執行的,innobackupex持續在備份innodb事務表期間,如果被執行DDL的表是在innobackupex備份完成之後發起,那麼在下一次scan lsn的時候innobackupex將發現DDL更改,報錯終止,如果是在備份非事務表期間發起的DDL,那麼將被FLUSH TABLE WITH READ LOCK語句阻塞。所以,對於使用innobackupex備份的生產環境,要執行DDL語句,也需要避開備份時間

那麼,除了這個,還有其他坑嗎?

  • 前面在介紹mysqldump備份過程中的FLUSH TABLES和FLUSH TABLES WITH READ LOCK語句的時候,提到過三個注意事項,innobackupex備份過程中為了獲得一個一致性備份,仍然會使用這兩個語句對資料庫進行重新整理表快取、加全域性讀鎖,也就是說,mysqldump使用這兩個語句可能會踩到的坑,在innobackupex中也會碰到,如下: 
    * 1)、如果一個會話中使用LOCK TABLES語句對某表加了表鎖,在該表鎖未釋放前,那麼另外一個會話如果執行FLUSH TABLES和FLUSH TABLES WITH READ LOCK語句會被阻塞,而如果資料庫中lock_wait_timeout引數設定時間太短,innobackupex將會因為執行FLUSH TABLES WITH READ LOCK語句獲取全域性讀鎖超時而導致備份失敗退出 
    * 2)、如果一個會話正在執行DDL語句,那麼另外一個會話如果執行FLUSH TABLES和FLUSH TABLES WITH READ LOCK語句會被阻塞,而如果資料庫中lock_wait_timeout引數設定時間太短,innobackupex將會因為執行FLUSH TABLES WITH READ LOCK語句獲取全域性讀鎖超時而導致備份失敗退出 
    * 3)、如果一個會話正在執行DML大事務(DML語句正在執行,資料正在發生修改,而不是使用lock in share mode和for update語句來顯式加鎖),那麼另外一個會話如果執行FLUSH TABLES和FLUSH TABLES WITH READ LOCK語句會被阻塞,而如果資料庫中lock_wait_timeout引數設定時間太短,innobackupex將會因為執行FLUSH TABLES WITH READ LOCK語句獲取全域性讀鎖超時而導致備份失敗退出

  • 但是,細心的童鞋可能已經發現了,innobackupex備份時的general_log中執行FLUSH NO_WRITE_TO_BINLOG TABLES語句之前,有這樣一句語句:SET SESSION lock_wait_timeout=31536000,備份時會在session級別把鎖超時時間改了,so…除了加表鎖忘記釋放之外,其他兩種情況估計不太可能碰到鎖超時的情況!!

當然,如果每天備份一次,那麼我們不太可能讓innobackupex在備份時,獲取全域性讀鎖時等待31536000秒,so……我們可以使用innobackupex的選項--kill-long-queries-timeout,來再獲取全域性讀鎖時,如果某查詢阻塞了獲得該FLUSH TABLE WITH READ LOCK語句時間超過這個閥值,那麼就對該會話執行kill,殺掉這個連線,當然,你也許會說對資料做修改的不能殺,只能殺查詢的,那麼我們可以使用--kill-long-query-type=all|select選項。下面列出這倆選項的含義:

  • --kill-long-query-type=all|select 
    * 該選項指定哪些型別的查詢在指定的查詢時間之後還沒有執行完成時被kill掉,以釋放阻塞加全域性讀鎖的鎖,預設值為all,有效值有:all和select 
    * 執行該選項需要有process和super許可權

  • --kill-long-queries-timeout=SECONDS

    * 該選項指定innobackupex在執行FLUSH TABLES WITH READ LOCK時碰到阻塞其獲得鎖的查詢時,等待該引數指定的秒數之後,如果仍然有查詢在執行,則執行kill掉這些查詢 
    * 預設值為0,表示innobackupex 不啟用嘗試kill掉任何查詢的功能

PS:

  • 很多人喜歡在備份前先flush binary logs一把,其實在有大事務對資料進行修改時,一不小心可能就會出現資料庫hang死,所以不建議這麼做

  • innobackupex備份期間,在資料庫中建立的連線不要誤殺,否則備份失敗


3、總  結


作為專職的DBA:

  • 我們一定一定要保持一種高度謹慎的態度,在資料庫備份方案選型時,一定要根據自己的業務場景充分測試,校驗,儘可能地把可能出現的深坑挖出來。

  • 除了尋找適合自己的,可行的備份方案之外,更應該做好備份校驗(備份是否成功完成、備份檔案是否損壞)、備份恢復演練(備份檔案是否可以正常恢復資料),以備不時之需。

  • 對生產庫的DDL操作、大事務、或者長時間鎖表的操作,一定要避開備份時間,否則,你懂的……

注:

本小節演示的xtrabackup版本基於2.4.4,如果xtrabackup版本小於2.3,備份過程中的系統呼叫有一些不太一樣,詳情請參考連結:http://mysql.taobao.org/monthly/2016/03/07/

全文參考連結:

  • https://dev.mysql.com/doc/refman/5.7/en/innodb-consistent-read.html

  • https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_single-transaction

  • https://dev.mysql.com/doc/refman/5.7/en/mysqldump.html#option_mysqldump_master-data

  • https://dev.mysql.com/doc/refman/5.7/en/commit.html

  • https://dev.mysql.com/doc/refman/5.7/en/flush.html

  • https://dev.mysql.com/doc/refman/5.7/en/log-destinations.html

  • https://dev.mysql.com/doc/refman/5.7/en/savepoint.html

  • https://www.percona.com/doc/percona-xtrabackup/LATEST/innobackupex/innobackupex_option_reference.html

下一篇"mysqldump與innobackupex備份過程你知多少(四)"我們將接著介紹"innobackupex”,精彩內容不容錯過,敬請期待!!

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

相關文章