標籤:單線程 www. 機制 tab 作用 防範 變化 存在 疑問
備份是資料安全的最後一道防線,對於任何資料丟失的情境,備份雖然不一定能恢複百分之百的資料(取決於備份周期),但至少能將損失降到最低。衡量備份恢複有兩個重要的指標:復原點目標(RPO)和恢復目標(RTO),前者重點關注能恢複到什麼程度,而後者則重點關注恢複需要多長時間。這篇文章主要討論MySQL的備份方案,重點介紹幾種備份方式的原理,包括檔案系統快照(LVM),邏輯備份工具Mysqldump,Mydumper,以及物理備份工具Xtrabackup,同時會詳細講解幾種方案的優缺點,以及可能遇到的問題。
冷備份
最簡單的備份方式就是,關閉MySQL伺服器,然後將data目錄下面的所有檔案進行拷貝儲存,需要恢複時,則將目錄拷貝到需要恢複的機器即可。這種方式確實方便,但是在生產環境中基本沒什麼作用。因為所有的機器都是要提供服務的,即使是Slave有時候也需要提供唯讀服務,所以關閉MySQL停服備份是不現實的。與冷備份相對應的一個概念是熱備份,所謂熱備份是在不影響MySQL對外服務的情況下,進行備份,熱備份是這篇文章討論的重點。
快照備份
首先要介紹的熱備份是快照備份,快照備份是指通過檔案系統支援的快照功能對資料庫進行備份。備份的原理是將所有的資料庫檔案放在同一分區中,然後對該分區執行快照工作,對於Linux而言,需要通過LVM(Logical Volumn Manager)來實現。LVM使用寫時複製(copy-on-write)技術來建立快照,例如,對整個卷的某個瞬間的邏輯副本,類似於資料庫中的innodb儲存引擎的MVCC,只不過LVM的快照在檔案系統層面,而MVCC在資料庫層面,而且僅支援innodb儲存引擎。LVM有一個快照預留地區,如果原始卷資料有變化時,LVM保證在任何變更寫入之前,會複製受影響塊到快照預留地區。簡單來說,快照地區內保留了快照點開始時的一致的所有old資料。對於更新很少的資料庫,快照也會非常小。對於MySQL而言,為了使用快照備份,需要將資料檔案,記錄檔都放在一個邏輯卷中,然後對該卷快照備份即可。由於快照備份,只能本地,因此,如果本地的磁碟損壞,則快照也就損壞了。快照備份更偏向於對誤操作防範,可以將資料庫迅速恢複到快照產生的時間點,然後結合二進位日誌可以恢複到指定的時間點。基本原理如:
邏輯備份
冷備份和快照備份由於其弊端在生產環境中很少使用,使用更多是MySQL內建的邏輯備份和物理備份工具,這節主要講邏輯備份,MySQL官方提供了Mysqldump邏輯備份工具,雖然已經足夠好,但存在單線程備份慢的問題。在社區提供了更優秀的邏輯備份工具mydumper,它的優勢主要體現在多線程備份,備份速度更快。
Mysqldump
Mysqldump用於備份,不得不提兩個關鍵的參數:
--single-transaction:在開始備份前,執行start transaction命令,以此來擷取一致性備份,該參數僅對innodb儲存引擎有效。
--master-data=2:主要用於記錄一致性備份的位點。
理解Mysqldump工作原理,一定要將事務表(innodb)和非事務表(比如myisam)區別對待,因為備份的流程與此息息相關。而且,到目前為止,我們也無法規避myisam表,即使我們的所有業務表都是innodb,因為mysql庫中系統資料表仍然採用的myisam表。備份的基本流程如下:
1.調用FTWRL(flush tables with read lock),全域禁止讀寫
2.開啟快照讀,擷取此時的快照(僅對innodb表起作用)
3.備份非innodb表資料(*.frm,*.myi,*.myd等)
4.非innodb表備份完畢後,釋放FTWRL鎖
5.逐一備份innodb表資料
6.備份完成。
整個過程,可以參考我同事的一張圖,但他的這張圖只考慮innodb表的備份情況,實際上在unlock tables執行完畢之前,非innodb表已經備份完畢,後面的t1,t2和t3實質都是innodb表,而且5.6的mysqldump利用儲存點機制,每備份完一個表就將一個表上的MDL鎖釋放,避免對一張表鎖更長的時間。這裡可以參考我之前的blog:FLUSH TABLE WITH READ LOCK
大家可能有一個疑問,為啥備份innodb表之前,就已經將鎖釋放掉了,這實際上是利用了innodb引擎的MVCC機制,開啟快照讀後,就能擷取那個時間的一致的資料,無論需要備份多長時間,直到整個事務結束(commit)為止。
Mydumper
Mydumper原理與Mysqldump原理類似,最大的區別是引入了多線程備份,每個備份線程備份一部分表,當然並發粒度可以到行級,達到多線程備份的目的。這裡要解決最大一個問題是,如何保證備份的一致性,其實關鍵還是在於FTWRL。對於非innodb表,在釋放鎖之前,需要將表備份完成。對於innodb表,需要確保多個線程都能拿到一致性位點,這個動作同樣要在持有全域鎖期間完成,因為此時資料庫沒有讀寫,可以保證位點一致。所以基本流程如下:
物理備份(Xtrabackup)
相對於邏輯備份利用查詢提取資料中的所有記錄,物理備份更直接,拷貝資料庫檔案和日誌來完成備份,因此速度會更快。當然,無論是開源的Mydumper還是官方最新的備份工具(5.7.11的mysqlpump)都支援了多線程備份,所以速度差異可能會進一步縮小,至少從目前生產環境來看,物理備份使用還是比較多的。由於Xtrabackup支援備份innodb表,實際生產環境中我們使用的工具是innobackupex,它是對xtrabackup的一層封裝。innobackupex 指令碼用來備份非 InnoDB 表,同時會調用 xtrabackup 命令來備份 InnoDB 表,innobackupex的基本流程如下:
1.開啟redo日誌拷貝線程,從最新的檢查點開始順序拷貝redo日誌;
2.開啟idb檔案拷貝線程,拷貝innodb表的資料
3.idb檔案拷貝結束,通知調用FTWRL,擷取一致性位點
4.備份非innodb表(系統資料表)和frm檔案
5.由於此時沒有新事務提交,等待redo日誌拷貝完成
6.最新的redo日誌拷貝完成後,相當於此時的innodb表和非innodb表資料都是最新的
7.擷取binlog位點,此時資料庫的狀態是一致的。
8.釋放鎖,備份結束。
Xtrabackup的改進
從前面介紹的邏輯備份和物理備份來看,無論是哪種備份工具,為了擷取一致性位點,都強依賴於FTWRL。這個鎖殺傷力非常大,因為持有鎖的這段時間,整個資料庫實質上不能對外提供寫服務的。此外,由於FTWRL需要關閉表,如有大查詢,會導致FTWRL等待,進而導致DML堵塞的時間變長。即使是備庫,也有SQL線程在複製來源於主庫的更新,上全域鎖時,會導致主備庫延遲。從前面的分析來看,FTWRL這把鎖持有的時間主要與非innodb表的資料量有關,如果非innodb表資料量很大,備份很慢,那麼持有鎖的時間就會很長。即使全部是innodb表,也會因為有mysql庫系統資料表存在,導致會鎖一定的時間。為瞭解決這個問題,Percona公司對Mysql的Server層做了改進,引入了BACKUP LOCK,具體而言,通過"LOCK TABLES FOR BACKUP"命令來備份非innodb表資料;通過"LOCK BINLOG FOR BACKUP"來擷取一致性位點,盡量減少因為Database Backup帶來的服務受損。我們看看採用這兩個鎖與FTWRL的區別:
LOCK TABLES FOR BACKUP
作用:備份資料
1.禁止非innodb表更新
2.禁止所有表的ddl
最佳化點:
1.不會被大查詢堵塞(關閉表)
2.不會堵塞innodb表的讀取和更新,這點非常重要,對於業務表全部是innodb的情況,則備份過程中DML完全不受損
UNLOCK TABLES
LOCK BINLOG FOR BACKUP
作用:擷取一致性位點。
1.禁止對位點更新的操作
最佳化點:
1.允許DDl和更新,直到寫binlog為止。
UNLOCK BINLOG
參考文檔
http://mysql.taobao.org/monthly/2016/03/07/
https://www.percona.com/blog/2014/03/11/introducing-backup-locks-percona-server-2/
http://www.wtoutiao.com/p/1cbstSx.html
http://www.wtoutiao.com/p/10cEnZ7.html
http://www.wtoutiao.com/p/125vVWi.html
http://www.wtoutiao.com/p/120AXSH.html
http://www.cnblogs.com/cchust/p/4603599.html
(轉)MySQL備份原理詳解