備份與恢復
從備份中恢復
更高級的恢復技術
復制和基于時間點的恢復使用的是相同的技術:服務器的二進制日志。這意味著復制在恢復時會是個非常有幫助的工具,哪怕方式不是很明顯。下面將演示一些可以用到的方法。這里列出來的不是一個完整的列表,但應該可以為你根據需求設計恢復方案帶來一些想法。記得編寫腳本,并且對恢復過程中需要用到的所有技術進行預演。shijian
- 1.用于快速恢復的延時復制
在前面已經提到,如果有一個延時的備庫,并且在備庫執行問題語句之前就發現了問題,那么基于時間點的恢復就更快更容易了。恢復的過程與前面說的有點不一樣,但思路是相同的。停止備庫,用START SLAVE UNTIL來重放事件直到要執行問題語句。接著,執行SET GLOBAL SQL _SLAVE_SKIP_COUNTER=1來跳過問題語句。如果想跳過多個事件,可以設置一個大于1的值(或簡單地使用CHANGE MASTER TO 來前移備庫在日志中的位置)。然后要做的就是執行START SLAVE,讓備庫執行完所有的中繼日志。這樣就利用貝克u完成了基于時間點的恢復中所有冗余的工作。現在可以將備庫提升為主庫,整個恢復過程基本上沒有中斷服務。即使沒有延時的備庫來加速恢復,普通的備庫也有好處,至少會把主庫的二進制日志復制到另外的及其上。如果主庫的磁盤壞了。備庫上的中繼日志可能就是唯一能夠獲取到的最接近主庫二進制的東西了 - 2.使用日志服務器進行恢復
還有另外一種使用復制來做恢復的方法:設置日志服務器。我們感覺復制比mysqlbinlog更可靠,mysqlbinlog可能會有一些導致異常行為的奇怪的Bug和不常見的情況。使用日志服務器進行恢復比mysqlbinlog更靈活更簡單,不僅因為START SLAVE UNTIL選項,還因為那些可以采用的復制規則(replicate-do-table)。使用日志服務器,相對其他的方式來說,可以做到更復雜的過濾。例如,使用日志服務器可以輕松地恢復單個表。而用mysqlbinlog和命令行工具則要困難得多——事實上,這樣做太復雜了,所以我們一般不建議進行嘗試。假設粗心的開發人員像前面地例子一樣刪除了同樣地表,現在想恢復此誤操作,但又不想讓整個服務器退到昨晚地備份。下面是利用日志服務器進行恢復地步驟: - 2.1 將需要恢復的服務器叫作server1
- 2.2 在另外一臺叫作server2的服務器上恢復做完的備份。在這臺服務器上運行恢復進程,以免在恢復時犯錯而導致事情更糟
- 2.3 按照前面的做法設置日志服務器來接收server1的二進制日志(復制日志到另外一個服務器并設置日志服務器是個好象發,但是要格外注意)
- 2.4 改變server2的配置文件,增加如下內容:
replicate-do-table=sakila.payment
- 2.5 重啟server2,然后用CHANGE MASTER TO來讓它成為日志服務器的備庫。配置它從昨晚備份的二進制日志坐標讀取。這時候切記不要運行START SLAVE
- 2.6 檢測server2上的SHOW SLAVE STATUS的輸出,驗證一切正常。要三思而行!
- 2.7 找到二進制日志中問題語句的位置,在server2上執行START SLAVE UNTIL來重放事件直到該位置。
- 2.8 在server2上用STOP SLAVE停掉復制進程。現在應該有被刪除表,因為現在從庫停止在被刪除之前的時間點
- 2.9 將所需表從server2復制到server1.
只有沒有任何多表的UPDATE、DELETE或INSERT語句操作這個表時,上述流程才是可行的。任何這樣的多表操作語句在被記錄的時候,可能時基于多個數據庫的狀態,而不僅僅時當前要恢復的這個數據庫,所以這樣恢復出來的數據可能和原始的有所不同。(只有在使用基于語句的二進制日志時才會有這個問題;如果使用的是基于行的日志,重放過程不會碰到這個問題)
InnoDB崩潰恢復
InnoDB在每次啟動時都會檢測數據和日志文件,以確認是否需要執行恢復過程。而且InnoDB的恢復過程與前面的討論不是一回事。它并不是恢復備份的數據;而是根據日志文件將事務應用到數據文件,將未提交的變更從數據文件中回滾。精確地描述InnoDB如何進行恢復工作,這有點太過復雜。我們要關注的焦點是當InnoDB有嚴重問題時如何實際執行恢復。大部分情況下InnoDB可以很好地解決問題。除非MySQL有Bug或硬件問題,否則不需要做任何非常規的事情,哪怕時服務器意外地斷電。InnoDB會在啟動時執行正常的恢復,然后一切就正常了,在日志文件中,可以看到如下信息。
InnoDB Doing recovery :scanned up to log sequence number 0 40817239
InnoDB: Starting an apply batch of log records to the database...
InnoDB會在日志文件中輸出恢復進度的百分比信息。有些人說直到整個過程完成才能看到這些信息。耐心點,這個恢復過程是急不來的。如果心急而殺掉進程并重啟,只會導致需要更長的恢復事件。如果服務器硬件有嚴重問題,例如內存或磁盤損壞,或遇到了MySQL或InnoDB的Bug,可能就不得不介入,這是要么進行強制恢復,要么阻止正常恢復發生。
InnoDB損壞的原因
InnoDB非常健壯且可靠,并且有許多的內建安全檢測來防止、檢測和修復損壞的數據——比其他MySQL存儲引擎要強很多。然而,InnoDB并不能保護自己避免一切錯誤。最起碼,InnoDB依賴于無緩存的IO調用和fsync()調用,直到數據完全地寫入到物理介質上才會返回。如果硬件不能保證寫入的持久化,InnoDB也就不能保證數據的持久,崩潰就有可能導致數據損壞。很多InnoDB損壞問題都是與硬件有關的(例如,因電力問題或內存損壞而導致損壞頁的寫入)。然而,在過往的經驗中,錯誤配置的硬件是更多的問題之源。常見的錯誤配置包括打開了不包含電池備份電源的RAID卡的回寫緩存,或打開了硬盤驅動器本身的回寫緩存。這些錯誤將會導致控制器或驅動器"撒謊",在數據實際上只寫入到回寫緩存上而不是磁盤上時,卻說fsync()已經完成。換句話說,硬件沒有提供保持InnoDB數據安全的保證。有時候及其默認就會這樣配置,因為這樣做可以得到更好的性能——對于某些場景確實很好,但是對事務數據服務來說卻是個大問題。如果在網絡附加存儲(NAS)上運行InnoDB,也可能會遇到損壞,因為對NAS設備來說完成fsync()只是意味著設備接收到了數據。如果InnoDB崩潰,數據是安全的,但如果是NAS設備崩潰就不一定了。嚴重的損壞會使InnoDB或MyISAM崩潰,而不那么嚴重的損壞則可能只是由于日志文件未真正同步到磁盤而丟掉了某些事務
如何恢復損壞的InnoDB數據
InnoDB損壞有三種主要類型,它們對數據恢復有著不同程度的要求.
- 1.二級索引損壞
一般可以用OPTIMIZE TABLE來修復損壞的二級索引;此外,也可以用SELECT INTO OUTFILE,刪除和重建表,然后LOAD DATA INFILE的方法。(也可以將表改為使用MyISAM再改回來)。這些過程都是通過構建一個新表重建受影響的索引,來修復損壞的索引數據 - 2.聚簇索引損壞
如果是聚簇索引損壞,也許只能使用innodb_forece_recovery選項來導出表。有時導出過程會讓InnoDB崩潰;如果出現這樣的情況,或許需要跳過導致崩潰的損壞頁以導出其他的記錄.聚簇索引的損壞比二級索引要更難修復,因為它會影響數據行本身,但在多數場合下只需要修復受影響的表。 - 3.損壞系統結構
系統結構包括InnoDB事務日志,表空間的撤銷日志(undo log)區域和數據字典。這種損壞可能需要做整個數據庫的導出和還原,因為InnoDB內部絕大部份的工作都可能受到影響
一般可以修復損壞的二級索引而不丟失數據。然而,另外兩種情形經常會引起數據的丟失。如果已經有備份,那最好還是從備份中還原,而不是試著從損壞的文件里區提取數據。如果必須從損壞的文件里提取數據,那一般過程是先嘗試讓InnoDB運行起來,然后使用SELECT INTO OUTFILE導出數據。如果服務器已經崩潰,并且每次啟動InnoDB都會崩潰,那么而可以配置InnoDB停止常規恢復和后臺進程的運行。這樣也許可以啟動服務器,然后在缺少或不做完整性檢查的情況下做邏輯備份。innodb_forece_recovery參數控制著InnoDB在啟動和常規操作時要做哪一種類型的操作。通常情況下這個值是0,可以增大到6.MySQL使用手冊里記錄了每個數值究竟會產生什么行為;再次我們不會重復這段信息,但是要告訴你:在有點危險的前提下,可以把這個數值調高到4.使用這個設置時,若有數據頁損壞,將會丟失一些數據;如果將數值設得更高,可能會從損壞的頁里提取到壞掉的數據。或者增加執行SELECT INTO OUTFILE時崩潰的風險。換句話說,這個值直到4都對數據沒有損害,但可能喪失修復問題的機會,而到5和6會更主動地修復問題,但損害數據的風險也會很大。當把innodb_force_recovery設為大于0的某個值時,InnoDB基本上是只讀的,但是仍然可以創建和刪除表。這可以阻止進一步的損壞,InnoDB會放松一些常規檢查,以便在發現壞數據時不會特意崩潰。在常規操作中,這樣做是由安全保障的。但是在恢復時,最好還是避免這樣做。如果需要執行InnoDB強制恢復,有個好主意是配置MySQL使它在操作完成之前不接受常規的連接請求。
如果InnoDB的數據損壞到了根本不能啟動MySQL的程度,還可以使用Percona出品的InnoDB Recovery Toolkit從表空間的數據文件里直接抽取數據。Percona Server還有允許服務器在某些表損壞時仍能運行的選項,而不是像MySQL那樣在單個表損壞頁被檢測出時就默認強制崩潰