MySQL資料災難挽救之ibdata檔案誤刪恢復

龍山游龍發表於2021-12-02

場景:開發人員的操作不當,在資料庫執行途中誤刪除了ibdata檔案和某些核心業務表的idb檔案,導致部分模組業務不可用.

思路:實際上,檔案已經被刪除一段時間。但是,只要mysqld在執行狀態中,即使檔案被刪除,這些檔案在物理上也會保持開啟狀態,它們仍舊存在於檔案系統中,mysqld的程式可以開啟這些檔案對其進行讀寫。

說明:發現檔案被誤刪了之後,千萬千萬不要關閉MySQL服務,一旦關閉了就找不回來了!

一、模擬ibdata誤刪除

shell> cd /data
shell> rm -rf ib_logfile*
shell> rm -rf ibdata1 
shell> rm -rf test/test.idb

二、恢復ibdata檔案

1、 前段業務關閉

mysql> flush tables with read lock;
Query OK, 0 rows affected (0.00 sec)

2、 將髒頁儘快刷入磁碟

mysql> set global innodb_max_dirty_pages_pct=0;
Query OK, 0 rows affected (0.00 sec)

3、 確保file和position的值沒有變化

mysql> show master status;
+------------------+----------+--------------+------------------+-------------------------------------------+
| File             | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set                         |
+------------------+----------+--------------+------------------+-------------------------------------------+
| mysql-bin.000006 |    10098 |              |                  | eb5f995b-1ff8-11ec-a358-000c292a2eb3:1-93 |
+------------------+----------+--------------+------------------+-------------------------------------------+
1 row in set (0.00 sec)

4、 確保髒頁已經刷入磁碟

mysql> show engine innodb status\G
*************************** 1. row ***************************
  Type: InnoDB
  Name: 
Status: 
=====================================
2021-12-02 15:47:17 0x7fbdf94fc700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 54 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 2 srv_active, 0 srv_shutdown, 173 srv_idle
srv_master_thread log flush and writes: 175
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 4
OS WAIT ARRAY INFO: signal count 4
RW-shared spins 0, rounds 8, OS waits 4
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 8.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS        #保undo log全部清除
------------
Trx id counter 7190026
Purge done for trxs n:o < 7190026 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421930039601888, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
---TRANSACTION 421930039600976, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,
 ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
485 OS file reads, 79 OS file writes, 21 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.19 writes/s, 0.09 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:
 insert 0, delete mark 0, delete 0
discarded operations:
 insert 0, delete mark 0, delete 0
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
Hash table size 276671, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG        #確保以下幾個值不會變化
---
Log sequence number 6070915710
Log flushed up to   6070915710
Pages flushed up to 6070915710
Last checkpoint at  6070915701
0 pending log flushes, 0 pending chkp writes
19 log i/o's done, 0.06 log i/o's/second
----------------------
BUFFER POOL AND MEMORY         #確保Modified db pages(髒頁數量)為0
----------------------
Total large memory allocated 1099431936
Dictionary memory allocated 117329
Buffer pool size   65528
Free buffers       65114
Database pages     414
Old database pages 0
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 380, created 34, written 52
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 414, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS        #確保無DML操作
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=2316, Main thread ID=140453764904704, state: sleeping
Number of rows inserted 1, updated 1, deleted 5, read 24
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================
1 row in set (0.00 sec)

5、 定位要恢復的檔案

找到mysqld的程式pid

shell> netstat -ntlp|grep mysqld
tcp6       0      0 :::3306                 :::*                    LISTEN      2316/mysqld

這裡是2316

只要mysqld不結束,就可以透過proc檔案系統找到這幾個被刪除的檔案(已經被Mark為deleted狀態)

shell> ll /proc/2316/fd | egrep 'ib_|ibdata|test'
lrwx------. 1 root root 64 Dec  2 15:49 10 -> /data/ib_logfile2 (deleted)
lrwx------. 1 root root 64 Dec  2 15:49 11 -> /data/ibdata1 (deleted)
lrwx------. 1 root root 64 Dec  2 15:49 23 -> /data/test/test.ibd(deleted)
lrwx------. 1 root root 64 Dec  2 15:49 4 -> /data/ib_logfile0 (deleted)
lrwx------. 1 root root 64 Dec  2 15:49 9 -> /data/ib_logfile1 (deleted)

需要恢復10 11 23 4 9 共五個檔案

6、 將檔案複製回原路徑

shell> cp /proc/2316/fd/10 /data/ib_logfile2
shell> cp /proc/2316/fd/11 /data/ibdata1
shell> cp /proc/2316/fd/4 /data/ib_logfile0
shell> cp /proc/2316/fd/9 /data/ib_logfile1
shell> cp /proc/2316/fd/23 /data/test/test.ibd

7、 修改檔案使用者組屬性

shell> chown mysql:mysql ibdata1
shell> chown mysql:mysql ib_logfile0
shell> chown mysql:mysql ib_logfile1
shell> chown mysql:mysql ib_logfile2
shell> chown mysql:mysql /data/test/test.ibd
shell> ll ib*
-rw-r-----. 1 mysql mysql  209715200 Dec  2 15:53 ibdata1
-rw-r-----. 1 mysql mysql 1048576000 Dec  2 15:53 ib_logfile0
-rw-r-----. 1 mysql mysql 1048576000 Dec  2 15:54 ib_logfile1
-rw-r-----. 1 mysql mysql 1048576000 Dec  2 15:52 ib_logfile2
shell> ll test/test.ibd
-rw-r-----. 1 mysql mysql 12582912 Dec  2 15:54 test.ibd

8、最後重啟MySQL服務

shell> service mysqld restart


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/30310891/viewspace-2845477/,如需轉載,請註明出處,否則將追究法律責任。

相關文章