Mysql

如何恢復文件被移動的 InnoDB 表

  • April 24, 2017

所以我有一個在複製流上設置的測試數據庫伺服器。在名稱上進行了優化,很快就填滿了從屬數據目錄上的空間。Mysql 盡職盡責地等待更多空間。

這個 datadir 是一個文件系統,只用作 mysql 的 datadir,所以沒有其他東西可以釋放。

我有一個 4 gig innodb 測試表,它不是複制流的一部分,所以我想我會嘗試一些東西來看看它是否可以工作,並且作為一個測試環境,如果出現可怕的錯誤,我並不太擔心。

這是我採取的步驟

  1. 衝了我要搬家的桌子
  2. 在它上面放置了一個讀鎖(即使沒有任何東西寫入它並且它不在複製流中)
  3. 將 .frm 和 .ibd 複製到帶有一些備用空間的文件系統
  4. 解鎖表
  5. 截斷該表 - 這為優化釋放了足夠的空間,以完成複制再次開始。
  6. 停止奴役/關閉mysql
  7. 將文件從 tmp 複製回數據目錄
  8. 重啟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 。我們使用了它,它幫助很大。我希望它對你有幫助。

引用自:https://dba.stackexchange.com/questions/6268