如何恢復文件被移動的 InnoDB 表
所以我有一個在複製流上設置的測試數據庫伺服器。在名稱上進行了優化,很快就填滿了從屬數據目錄上的空間。Mysql 盡職盡責地等待更多空間。
這個 datadir 是一個文件系統,只用作 mysql 的 datadir,所以沒有其他東西可以釋放。
我有一個 4 gig innodb 測試表,它不是複制流的一部分,所以我想我會嘗試一些東西來看看它是否可以工作,並且作為一個測試環境,如果出現可怕的錯誤,我並不太擔心。
這是我採取的步驟
- 衝了我要搬家的桌子
- 在它上面放置了一個讀鎖(即使沒有任何東西寫入它並且它不在複製流中)
- 將 .frm 和 .ibd 複製到帶有一些備用空間的文件系統
- 解鎖表
- 截斷該表 - 這為優化釋放了足夠的空間,以完成複制再次開始。
- 停止奴役/關閉mysql
- 將文件從 tmp 複製回數據目錄
- 重啟mysql
.err 日誌中沒有顯示任何內容,看起來不錯。我連接並使用 mydb;並查看我在展示表中弄亂的表。但是,如果我嘗試
select * from testtable limit 10;
我得到錯誤
ERROR 1146 (42S02): Table 'mydb.testtable' doesn't exist
據我所知,到目前為止,我可以很好地從所有其他表中讀取數據,並且複制開始備份而沒有任何抱怨。
我能做些什麼來從這一點上恢復過來嗎?如果需要,我可以從頭開始重建它,但很好奇其他人對這個冒險的看法。我採取的一系列步驟是否會以更完美的結果結束?
如果這不是一個測試伺服器,我不能只是“現場直播”看看會發生什麼?如果我必須這樣,有什麼最好的方法可以暫時釋放生產從屬伺服器上的空間?
大多數人忘記 TRUNCATE TABLE 的最大事情是TRUNCATE TABLE 是 DDL 而不是 DML。在 InnoDB 中,ibdata1 中的元數據包含 InnoDB 表的編號列表。使用 TRUNCATE TABLE 會導致 InnoDB 表的內部元數據 id 發生變化。發生這種情況是因為 TRUNCATE TABLE 有效地執行了以下操作:
範例:截斷名為 mydb.mytb 的 InnoDB 表
USE mydb CREATE TABLE newtb LIKE mytb; ALTER TABLE mytb RENAME oldtb; ALTER TABLE newtb RENAME mytb; DROP TABLE oldtb;
因此,新的 mytb 將具有不同的內部元數據 ID。
當您將 .ibd 文件複製到其他位置時,.ibd 中包含原始內部元數據 ID。簡單地放回 .ibd 文件不會導致內部元數據 id 與 ibdata1 中的一致。
你應該做的是:
複製 InnoDB 表的 .ibd 文件。然後,執行這個
ALTER TABLE tablename DISCARD TABLESPACE;
要稍後將其恢復,請將 .ibd 文件複製回 datadir,然後執行
ALTER TABLE tablename IMPORT TABLESPACE;
這將保留內部元數據 ID。
確保 .frm 始終存在。
我曾經幫助一個客戶以同樣的方式恢復了 30 個 InnoDB 表。我不得不使用另一個數據庫伺服器並通過添加和刪除 InnoDB 表來玩一些遊戲來尋找正確的內部元數據 ID。
客戶發現這篇文章:http ://www.chriscalender.com/?tag=innodb-error-tablespace-id-in-file 。我們使用了它,它幫助很大。我希望它對你有幫助。