公眾號 :碼農架構
MySQL 的複製主要是通過 Binlog 來完成的,Binlog 記錄了資料庫更新的事件,從庫 I/O 線程會向主庫發送 Binlog 更新的請求,同時主庫二進位轉儲線程會發送 Binlog 給從庫作為中繼日誌進行保存,然後從庫會通過中繼日誌重放,完成資料庫的同步更新,看來是一套完美的的災備方案!但是有沒有經歷過「手抖」後的「絕望」。
嗯!你志哥以前幹過
直接在生產環境中對數據進行操作,或者忘記了當前是在開發環境,還是在生產環境中,就直接對資料庫進行操作。
當然如果我們對資料庫做過時間點備份,也可以直接恢復到該時間點。不過我們今天要討論的是一個特殊的情況,也就是在沒做資料庫備份,沒有開啟使用 Binlog 的情況下,儘可能地找回數據。
今天的分享內容主要包括以下幾個部分
InnoDB 存儲引擎的表空間
InnoDB 存儲引擎的文件格式是.ibd 文件,數據會按照表空間(tablespace)進行存儲,分為共享表空間和獨立表空間。如果想要查看表空間的存儲方式,我們可以對innodb_file_per_table變量進行查詢,使用show variables like &39;;。ON 表示獨立表空間,而 OFF 則表示共享表空間。
如果採用共享表空間的模式,InnoDB 存儲的表數據都會放到共享表空間中,也就是多個數據表共用一個表空間,同時表空間也會自動分成多個文件存放到磁碟上。這樣做的好處在於單個數據表的大小可以突破文件系統大小的限制,最大可以達到 64TB,也就是 InnoDB 存儲引擎表空間的上限。不足也很明顯,多個數據表存放到一起,結構不清晰,不利於數據的找回,同時將所有數據和索引都存放到一個文件中,也會使得共享表空間的文件很大。
採用獨立表空間的方式可以讓每個數據表都有自己的物理文件,也就是 table_name.ibd 的文件,在這個文件中保存了數據表中的數據、索引、表的內部數據字典等信息。它的優勢在於每張表都相互獨立,不會影響到其他數據表,存儲結構清晰,利於數據恢復,同時數據表還可以在不同的資料庫之間進行遷移。
如果.ibd 文件損壞了,數據如何找回
如果我們之前沒有做過全量備份,也沒有開啟 Binlog,那麼我們還可以通過.ibd 文件進行數據恢復,採用獨立表空間的方式可以很方便地對資料庫進行遷移和分析。如果我們誤刪除(DELETE)某個數據表或者某些數據行,也可以採用第三方工具回數據。
我們這裡可以使用 Percona Data Recovery Tool for InnoDB 工具,能使用工具進行修復是因為我們在使用 DELETE 的時候是邏輯刪除。我們之前學習過 InnoDB 的頁結構,在保存數據行的時候還有個刪除標記位,對應的是頁結構中的 delete_mask 屬性,該屬性為 1 的時候標記了記錄已經被邏輯刪除,實際上並不是真的刪除。不過當有新的記錄插入的時候,被刪除的行記錄可能會被覆蓋掉。所以當我們發生了 DELETE 誤刪除的時候,一定要第一時間停止對誤刪除的表進行更新和寫入,及時將.ibd 文件拷貝出來並進行修復。
如果已經開啟了 Binlog,就可以使用閃回工具,比如 mysqlbinlog 或者 binlog2sql,從工具名稱中也能看出來它們都是基於 Binlog 來做的閃回。原理就是因為 Binlog 文件本身保存了資料庫更新的事件(Event),通過這些事件可以幫我們重現資料庫的所有更新變化,也就是 Binlog 回滾
innodb_force_recovery參數一共有 7 種狀態,除了默認的 0 以外,還可以為 1-6 的取值,分別代表不同的強制恢復措施。
當我們需要強制恢復的時候,可以將innodb_force_recovery設置為 1,表示即使發現了損壞頁也可以繼續讓服務運行,這樣我們就可以讀取數據表,並且對當前損壞的數據表進行分析和備份。
通常innodb_force_recovery參數設置為 1,只要能正常讀取數據表即可。但如果參數設置為 1 之後還無法讀取數據表,我們可以將參數逐一增加,比如 2、3 等。一般來說不需要將參數設置到 4 或以上,因為這有可能對數據文件造成永久破壞。另外當innodb_force_recovery設置為大於 0 時,相當於對 InnoDB 進行了防寫,只能進行 SELECT 讀取操作,還是有限制的讀取,對於 WHERE 條件以及 ORDER BY 都無法進行操作。
當我們開啟了強制恢復之後,資料庫的功能會受到很多限制,我們需要儘快把有問題的數據表備份出來,完成數據恢復操作。整體的恢復步驟可以按照下面的思路進行:
【公眾號:碼農架構】
分享、點讚、在看,給個三連擊唄!