mysql innodb 從 ibd 文件恢復表數據

来源:https://www.cnblogs.com/dreamanddead/archive/2018/09/27/recover-mysql-innodb-table-data-from-ibd-file.html
-Advertisement-
Play Games

最近內部的 mysql 資料庫發生了一件奇怪的事,其中有一個表 users625 突然出現問題, 所有對它的操作都報錯誤 。 它還顯示在列表裡,在 mysql 數據目錄中也可以找到對應的表文件,也沒有 進行過刪除操作,突然出現這樣的錯誤非常奇怪。 <! more 內部運行環境: | 名稱 | 值 | ...


最近內部的 mysql 資料庫發生了一件奇怪的事,其中有一個表 users625 突然出現問題,
所有對它的操作都報錯誤 數據表不存在

mysql> select count(*) from users625;
ERROR 1146 (42S02): Table 'km8.users625' doesn't exist

show tables 它還顯示在列表裡,在 mysql 數據目錄中也可以找到對應的表文件,也沒有
進行過刪除操作,突然出現這樣的錯誤非常奇怪。

內部運行環境:

名稱
OS Debian Squeeze x64
mysql 版本 5.1
mysql 引擎 innodb

發生了什麼

突然出現這種情況,第一反應必定是想辦法將表中的用戶數據找回,但是目前發生問題的情況與原因都不明晰,
不能輕舉妄動。

查看 mysql 日誌,在操作出錯的時候,日誌這樣顯示:

mysqld: 180926 11:10:53  InnoDB: cannot calculate statistics for table km8/users625
mysqld: InnoDB: because the .ibd file is missing.  For help, please refer to
mysqld: InnoDB: http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
mysqld: 180926 11:10:53 [ERROR] MySQL is trying to open a table handle but the .ibd file for
mysqld: table km8/users625 does not exist.
mysqld: Have you deleted the .ibd file from the database directory under
mysqld: the MySQL datadir, or have you used DISCARD TABLESPACE?
mysqld: See http://dev.mysql.com/doc/refman/5.1/en/innodb-troubleshooting.html
mysqld: how you can resolve the problem.

其中提到3個可追溯的點:

瞭解這3點提到的內容,應該對判斷情況有很好的幫助。

ibd file

日誌中提問,是否丟失了 ibd 文件?先到 mysql 數據目錄下查找,

.
├── ibdata1
├── .......
├── .......
└── km8
    ├── ............
    ├── ............
    ├── users625.frm
    ├── users625.ibd
    ├── ............
    └── ............

users625 的 ibd 文件是存在的,與之一起的還有文件 users625.frm 。

根據官方文檔對 frm 文件的描述,frm 文件是用來保存 table 表結構(即 table 的定義)的,無論使用什麼存儲引擎。

與之相對的,ibd 文件是用來存儲表數據(即行數據)的,通常情況下,所有數據都會存儲在系統的 ibd 文件,
但是當開啟選項 innodb_file_per_table 的時候,每個表的數據會使用單獨的 ibd 文件來存儲。

當前的 mysql 就開啟了這個選項,

[mysqld]
innodb_file_per_table=1

目前 frm 與 ibd 文件都存在,從中恢複數據便存在一些希望。

DISCARD TABLESPACE

日誌中提到的 DISCARD TABLESPACE 其實是在猜測導致 ibd 文件丟失的原因,因為它會刪除相應 table 的 ibd 文件(所謂 tablespace)。

> ALTER TABLE km8.users625 DISCARD TABLESPACE;

底層的 users625.ibd 文件就會被刪除,丟失所有表數據。

根據目前情況來看, ibd 文件還存在,所以它不是導致錯誤的原因。

trouble shooting doc

日誌中提到的參考鏈接,其中列舉了多種情況,和當前問題相關的是一個子鏈接
按照它提供的方法,嘗試進行數據恢復。

數據恢復

官方文檔提到的恢複數據的方法,思路很清晰:

  1. 啟用相同版本的 mysql 實例(啟用選項 innodb_file_per_table)
  2. 建立同樣結構的數據表
  3. 替換 ibd 文件(保持文件許可權一致)
  4. 導入 ibd 文件中的數據
  5. 使用 mysqldump,導出數據
  6. 將導出的數據導入原資料庫

我按照這種方式嘗試恢複數據,並不是那麼順利:

如何獲得 table 表結構?

在第2步,需要建立同樣結構的數據表,目前只有 frm 和 ibd 文件,怎麼樣得到 create table 命令?

根據底層數據存儲的理解,table 表結構存儲在 frm 文件中,而目前已經有相應的方法從中提取出 create table 命令,
這樣就可以用於在新的 mysql 實例中建立 table 。

tablespace id 不對應?

在第4步,嘗試導入數據的時候,

> ALTER TABLE km8.users625 IMPORT TABLESPACE;
ERROR 1030 (HY000): Got error -1 from storage engine

總是出現失敗,同時在 mysql 新實例的日誌中發現這樣的錯誤:

mysqld: InnoDB: Error: tablespace id in file './km8/users625.ibd' is 18446744073709551615, but in the InnoDB
mysqld: InnoDB: data dictinary it is 1.

原來在內部,ibd 文件本身有一個 id,必須和 mysql innodb 內部的 table 元數據相對應,才可以進行導入。

根據錯誤信息搜索到一篇文章,其中提到兩種辦法:

  1. 重覆建表,因為 mysql 內部的 tablespace id 是累計遞增的,預先建立 (18446744073709551615 - 1)張表,再建立
    users625 表,就可以對應 id,併進行導入。
  2. 修改 ibd 文件,因為 tablespace id 存儲於 ibd 文件,找到它並將其修改為 1,使之與內部的 id 對應,就可以進行導入。

考慮第 1 種方法,要預先建立上億張空表?!這根本不可能。

於是嘗試第 2 種方法,研究 ibd 的文件格式,修改對應 id。

用二進位編輯器打開 users625.ibd 文件,

users625-ibd-hexdump

18:26:08 UTC - mysqld got signal 6. This could be because you hit a bug. It is also possible that this
binary or one of the libraries it was linked against is corrupt, improperly built or misconfigured.
This error can also be cuased by malfunctioning hardware.

不敢相信自己的眼睛,居然有錯誤 log 在二進位文件里?!ibd 的文件格式可沒有這麼說明過。

隨便找一個鄰居表正常的 ibd 文件作對比,

normal-ibd-hexdump

看來是出現了 bug ,崩潰的環境直接將數據文件給毀了,這也解釋了為什麼 tablespace id 會那麼大,因為 log
覆蓋了原本的 id 欄位,使 mysql 解讀出了一個好笑的數字。

暫時放棄

這種情況下,還沒有辦法將數據恢復回來,只能暫時將表刪除,新建空表,保證上層應用程式可以運行。
將 ibd 文件備份下來,看後續還沒有其它的辦法將其恢復。

檢測所有 table 狀態

當前只發現一個出現問題的 table ,可能同時也有其它的 table 出現問題。對此需要做一個全面的檢測,
檢測有沒有其它的表受到牽連。

$ mysqlcheck --all-databases

寫在最後

資料庫的備份是非常重要的!直接導入備份數據,是解決問題最保險最便捷的辦法。
如果沒有備份,遇到 bug 丟失數據,只能怪時運不濟。

同時資料庫也最好選擇穩定的版本,降低出現 bug 的概率。


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 上一篇講了什麼是OpenVAS以及如何安裝: https://www.cnblogs.com/xuyiqing/p/9690373.html 接下來就是使用: 我先打開一臺Metasploitable機器:192.168.163.129 windows2003機器:192.168.163.130 打 ...
  • 一、驅動部分 首先向NXP 的 fae要android 6.0 bring up的代碼,如: 結構目錄如下: 1. 添加驅動文件 高通平臺需使用 節點,所以將驅動中的設備節點名字修改為 即可; 2. 修改平臺配置 在init.qcom.rc中增加節點的許可權,並創建 文件夾 3. 修改HAL代碼: 替 ...
  • samba服務搭建 sudo apt-get install samba sudo vim /etc/samba/smb.conf workgroup = szsoft 設置用戶密碼登陸方式security=user 不需要用戶密碼登陸配置 [share] path = /home/username ...
  • 出現這樣的原因是修改了表的結構,沒有重新編譯視圖,這種情況出現的幾率很少,並不是沒有。 解決方法:重新編譯一下該視圖。 視圖是一個虛表,是從一個或幾個基本表(或視圖)中導出的表,在系統的數據字典中僅存放了視圖的定義,不存放視圖對應的數據,視圖所對應的數據不會進行存儲。如果我們把基礎表的架構更改了,並 ...
  • 關於MySQL的優化,相信很多人都聽過這一條:避免使用select *來查找欄位,而是要在select後面寫上具體的欄位。 那麼這麼做的原因相信大家都應該知道:減少數據量的傳輸。 但我要講的是另外一個原因:使用select *,就基本不可能使用到覆蓋索引(什麼是覆蓋索引,後面會說)。 而將一個本該可 ...
  • substr:字元串截取。 1、substr:(字元串 | 列 ,開始點):從開始一直截取到結尾。 select substr(zym,2) from bqh4 2、substr:(字元串 | 列 ,開始點 結束點):從開始-結束截取 select substr(zym,2,5) from bqh4 ...
  • 常用的欄位數據類型: .字元串(varchar2(n)) n表示保存最大長度,基本200作用。.整數(number(n)) n位的整數,也可用int代替.小數(number(n,m)) m為小數位,n-m為整數位,有時候用float代替.日期(date) 存放日期.大文本(clob) 存儲海量文字( ...
  • 1、首先先創建一個文件夾存放資料庫目錄:d:cs 用戶及密碼為cs 2、創建表空間: create tablespace csdatafile 'O:\cs\cs.dbf' size 50M autoextend on next 10M maxsize unlimited logging exten ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...