1、打開navicat工具,連接上mysql數(shù)據(jù)庫(kù),選擇一個(gè)數(shù)據(jù)庫(kù)(我們這里為了演示,選擇一個(gè)測(cè)試數(shù)據(jù)庫(kù))。在上方菜單欄,選擇備份,然后在備份列表中,選擇一個(gè)備份文件,點(diǎn)擊"還原備份"
創(chuàng)新互聯(lián)公司不只是一家網(wǎng)站建設(shè)的網(wǎng)絡(luò)公司;我們對(duì)營(yíng)銷、技術(shù)、服務(wù)都有自己獨(dú)特見解,公司采取“創(chuàng)意+綜合+營(yíng)銷”一體化的方式為您提供更專業(yè)的服務(wù)!我們經(jīng)歷的每一步也許不一定是最完美的,但每一步都有值得深思的意義。我們珍視每一份信任,關(guān)注我們的成都做網(wǎng)站、成都網(wǎng)站設(shè)計(jì)質(zhì)量和服務(wù)品質(zhì),在得到用戶滿意的同時(shí),也能得到同行業(yè)的專業(yè)認(rèn)可,能夠?yàn)樾袠I(yè)創(chuàng)新發(fā)展助力。未來(lái)將繼續(xù)專注于技術(shù)創(chuàng)新,服務(wù)升級(jí),滿足企業(yè)一站式成都全網(wǎng)營(yíng)銷推廣需求,讓再小的品牌網(wǎng)站制作也能產(chǎn)生價(jià)值!
navicat41.png
2、在還原備份的對(duì)話框中,默認(rèn)顯示常規(guī)選項(xiàng),里面顯示的是備份文件的詳細(xì)信息。這里注意核對(duì)信息和時(shí)間點(diǎn),放在恢復(fù)到錯(cuò)誤的版本
navicat42.png
3、切換到"選擇對(duì)象"選項(xiàng),勾選需要恢復(fù)的數(shù)據(jù)對(duì)象,默認(rèn)全部勾選,全量恢復(fù)即可
navicat43.png
4、切換到"高級(jí)"選項(xiàng),可以針對(duì)服務(wù)器選項(xiàng)和對(duì)象選項(xiàng),勾選對(duì)應(yīng)的選項(xiàng),如果你不想覆蓋現(xiàn)有的函數(shù),則把對(duì)應(yīng)的勾選去掉即可
navicat44.png
5、配置勾選完成之后,信息確認(rèn)完成。則可以點(diǎn)擊"開始"按鈕,進(jìn)行還原備份。這里會(huì)有一個(gè)確認(rèn)對(duì)話框,點(diǎn)擊確認(rèn)開發(fā)恢復(fù)?;謴?fù)完成之后,會(huì)在日志信息里提示"[Msg] Finished - Successfully",表示恢復(fù)完成。
navicat45.png
navicat46.png
6、針對(duì)備份文件,除了可以選擇還原備份之外,還可以選擇"提取SQL",這個(gè)功能可以從之前的備份文件中,抽取出sql語(yǔ)句,然后從sql語(yǔ)句中,選擇對(duì)應(yīng)的數(shù)據(jù)進(jìn)行增量恢復(fù)或用作數(shù)據(jù)比對(duì)。
1、首先構(gòu)建測(cè)試環(huán)境數(shù)據(jù)create table t1(a varchar(10),b varchar(10));insert into t1 values('1','1');insert into t1 values('2','2');commit;。
2、模擬誤修改,將t1表中的b字段更新為錯(cuò)誤數(shù)據(jù) "123456"update t1 set b='123456' where a='1';commit;select * from t1;。
3、將恢復(fù)工具上傳到服務(wù)器并進(jìn)行解壓。unzip binlog2sql-master.zip。
4、得到誤修改時(shí)的binlog文件(show binary logs;),實(shí)驗(yàn)環(huán)境是mysql-bin.000011。
5、通過(guò)?binlog2sql.py 腳本的到所有 對(duì)表 t1 的修改操作。python binlog2sql.py -hlocalhost -P23307 -ubinlog2sql -p'binlog2sql' -dtest -tt1 --start-file='mysql-bin.000011'。
6、得到了誤刪除的sql的準(zhǔn)確位置在1382-1615之間,使用 _**-B**_ 選項(xiàng)生成回滾sql。python binlog2sql.py -hlocalhost -P23307 -ubinlog2sql -p'binlog2sql' -dtest -tt1 --start-file='mysql-bin.000011' --start-position=1382 --stop-position=1615 -B。
7、執(zhí)行得到的回滾語(yǔ)句進(jìn)行誤操作恢復(fù)。就完成了。
每個(gè) DBA 是不是都有過(guò)刪庫(kù)的經(jīng)歷?刪庫(kù)了沒(méi)有備份怎么辦?備份恢復(fù)后無(wú)法啟動(dòng)服務(wù)什么情況?表定義損壞數(shù)據(jù)無(wú)法讀取怎么辦?
我曾遇到某初創(chuàng)互聯(lián)網(wǎng)企業(yè),因維護(hù)人員不規(guī)范的備份恢復(fù)操作,導(dǎo)致系統(tǒng)表空間文件被初始化,上萬(wàn)張表無(wú)法讀取,花了數(shù)小時(shí)才搶救回來(lái)。
當(dāng)你發(fā)現(xiàn)數(shù)據(jù)無(wú)法讀取時(shí),也許并非數(shù)據(jù)丟失了,可能是 DBMS 找不到描述數(shù)據(jù)的信息。
背景
先來(lái)了解下幾張關(guān)鍵的 InnoDB 數(shù)據(jù)字典表,它們保存了部分表定義信息,在我們恢復(fù)表結(jié)構(gòu)時(shí)需要用到。
SYS_TABLES 描述 InnoDB 表信息CREATE TABLE `SYS_TABLES` (`NAME` varchar(255) NOT NULL DEFAULT '', ?表名`ID` bigint(20) unsigned NOT NULL DEFAULT '0', ?表id`N_COLS` int(10) DEFAULT NULL,`TYPE` int(10) unsigned DEFAULT NULL,`MIX_ID` bigint(20) unsigned DEFAULT NULL,`MIX_LEN` int(10) unsigned DEFAULT NULL,`CLUSTER_NAME` varchar(255) DEFAULT NULL,`SPACE` int(10) unsigned DEFAULT NULL, ? 表空間idPRIMARY KEY (`NAME`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_INDEXES 描述 InnoDB 索引信息CREATE TABLE `SYS_INDEXES` ( ?`TABLE_ID` bigint(20) unsigned NOT NULL DEFAULT '0', 與sys_tables的id對(duì)應(yīng) ?`ID` bigint(20) unsigned NOT NULL DEFAULT '0', ?索引id ?`NAME` varchar(120) DEFAULT NULL, ? ? ? ? 索引名稱 ?`N_FIELDS` int(10) unsigned DEFAULT NULL, 索引包含字段的個(gè)數(shù) ?`TYPE` int(10) unsigned DEFAULT NULL, ?`SPACE` int(10) unsigned DEFAULT NULL, ?存儲(chǔ)索引的表空間id ?`PAGE_NO` int(10) unsigned DEFAULT NULL, ?索引的root page id ?PRIMARY KEY (`TABLE_ID`,`ID`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_COLUMNS 描述 InnoDB 表的字段信息CREATE TABLE `SYS_COLUMNS` ( ?`TABLE_ID` bigint(20) unsigned NOT NULL, 與sys_tables的id對(duì)應(yīng) ?`POS` int(10) unsigned NOT NULL, ? ? 字段相對(duì)位置 ?`NAME` varchar(255) DEFAULT NULL, ? ?字段名稱 ?`MTYPE` int(10) unsigned DEFAULT NULL, ?字段編碼 ?`PRTYPE` int(10) unsigned DEFAULT NULL, 字段校驗(yàn)類型 ?`LEN` int(10) unsigned DEFAULT NULL, ?字段字節(jié)長(zhǎng)度 ?`PREC` int(10) unsigned DEFAULT NULL, 字段精度 ?PRIMARY KEY (`TABLE_ID`,`POS`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;SYS_FIELDS 描述全部索引的字段列CREATE TABLE `SYS_FIELDS` ( ?`INDEX_ID` bigint(20) unsigned NOT NULL, ?`POS` int(10) unsigned NOT NULL, ?`COL_NAME` varchar(255) DEFAULT NULL, ?PRIMARY KEY (`INDEX_ID`,`POS`)) ENGINE=InnoDB DEFAULT CHARSET=latin1;./storage/innobase/include/dict0boot.h 文件定義了每個(gè)字典表的 index id,對(duì)應(yīng) id 的 page 中存儲(chǔ)著字典表的數(shù)據(jù)。
這里我們需要借助 undrop-for-innodb 工具恢復(fù)數(shù)據(jù),它能讀取表空間信息得到 page,將數(shù)據(jù)從 page 中提取出來(lái)。
# wget yum install -y gcc flex bison# make# make sys_parser
# ./sys_parser 讀取表結(jié)構(gòu)信息
sys_parser [-h] [-u] [-p] [-d] databases/table
stream_parser 讀取 InnoDB page 從 ibdata1 或 ibd 或分區(qū)表
# ./stream_parserYou must specify file with -f optionUsage: ./stream_parser -f innodb_datafile [-T N:M] [-s size] [-t size] [-V|-g] ?Where: ? ?-h ? ? ? ? - Print this help ? ?-V or -g ? - Print debug information ? ?-s size ? ?- Amount of memory used for disk cache (allowed examples 1G 10M). Default 100M ? ?-T ? ? ? ? - retrieves only pages with index id = NM (N - high word, M - low word of id) ? ?-t size ? ?- Size of InnoDB tablespace to scan. Use it only if the parser can't determine it by himself.
c_parser 從 innodb page 中讀取記錄保存到文件
# ./c_parserError: Usage: ./c_parser -4|-5|-6 [-dDV] -f InnoDB page or dir -t table.sql [-T N:M] [-b external pages directory] ?Where ? ?-f InnoDB page(s) -- InnoDB page or directory with pages(all pages should have same index_id) ? ?-t table.sql -- CREATE statement of a table ? ?-o file -- Save dump in this file. Otherwise print to stdout ? ?-l file -- Save SQL statements in this file. Otherwise print to stderr ? ?-h ?-- Print this help ? ?-d ?-- Process only those pages which potentially could have deleted records (default = NO) ? ?-D ?-- Recover deleted rows only (default = NO) ? ?-U ?-- Recover UNdeleted rows only (default = YES) ? ?-V ?-- Verbose mode (lots of debug information) ? ?-4 ?-- innodb_datafile is in REDUNDANT format ? ?-5 ?-- innodb_datafile is in COMPACT format ? ?-6 ?-- innodb_datafile is in MySQL 5.6 format ? ?-T ?-- retrieves only pages with index id = NM (N - high word, M - low word of id) ? ?-b dir -- Directory where external pages can be found. Usually it is pages-XXX/FIL_PAGE_TYPE_BLOB/ ? ?-i file -- Read external pages at their offsets from file. ? ?-p prefix -- Use prefix for a directory name in LOAD DATA INFILE command
接下來(lái),我們演示場(chǎng)景的幾種數(shù)據(jù)恢復(fù)場(chǎng)景。
場(chǎng)景1:drop table
是否啟用了 innodb_file_per_table 其恢復(fù)方法有所差異,當(dāng)發(fā)生誤刪表時(shí),應(yīng)盡快停止MySQL服務(wù),不要啟動(dòng)。若 innodb_file_per_table=ON,最好只讀方式重新掛載文件系統(tǒng),防止其他進(jìn)程寫入數(shù)據(jù)覆蓋之前塊設(shè)備的數(shù)據(jù)。
如果評(píng)估記錄是否被覆蓋,可以表中某些記錄的作為關(guān)鍵字看是否能從 ibdata1 中篩選出。
#?grep WOODYHOFFMAN ibdata1
Binary file ibdata1 matches
也可以使用 bvi(適用于較小文件)或 hexdump -C(適用于較大文件)工具
以表 sakila.actor 為例CREATE TABLE `actor` (`actor_id` smallint(5) unsigned NOT NULL AUTO_INCREMENT,`first_name` varchar(45) NOT NULL,`last_name` varchar(45) NOT NULL,`last_update` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`actor_id`),KEY `idx_actor_last_name` (`last_name`)) ENGINE=InnoDB AUTO_INCREMENT=201 DEFAULT CHARSET=utf8
首先恢復(fù)表結(jié)構(gòu)信息1. 解析系統(tǒng)表空間獲取 page 信息
./stream_parser -f /var/lib/mysql/ibdata1
2. 新建一個(gè) schema,把系統(tǒng)字典表的 DDL 導(dǎo)入
cat dictionary/SYS_* | mysql recovered
3. 創(chuàng)建恢復(fù)目錄
mkdir -p dumps/default
4. 解析系統(tǒng)表空間包含的字典表信息,
./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql dumps/default/SYS_TABLES 2 dumps/default/SYS_TABLES.sql./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000002.page -t dictionary/SYS_COLUMNS.sql dumps/default/SYS_COLUMNS 2 dumps/default/SYS_COLUMNS.sql./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql dumps/default/SYS_INDEXES 2 dumps/default/SYS_INDEXES.sql./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000004.page -t dictionary/SYS_FIELDS.sql dumps/default/SYS_FIELDS 2 dumps/default/SYS_FIELDS.sql
5. 導(dǎo)入恢復(fù)的數(shù)據(jù)字典
cat dumps/default/*.sql | mysql recovered
6. 讀取恢復(fù)后的表結(jié)構(gòu)信息
./sys_parser -pmsandbox -d recovered sakila/actor
由于 5.x 版本 innodb 引擎并非完整記錄表結(jié)構(gòu)信息,會(huì)丟失 AUTO_INCREMENT 屬性、二級(jí)索引和外鍵約束, DECIMAL 精度等信息。
若是 mysql 5.5 版本 frm 文件被從系統(tǒng)刪除,在原目錄下 touch 與原表名相同的 frm 文件,還能讀取表結(jié)構(gòu)信息和數(shù)據(jù)。若只有 frm 文件,想要獲得表結(jié)構(gòu)信息,可使用 mysqlfrm --diagnostic /path/to/xxx.frm,連接 mysql 會(huì)顯示字符集信息。
innodb_file_per_table=OFF
因?yàn)槭枪蚕肀砜臻g模式,數(shù)據(jù)頁(yè)都存儲(chǔ)在 ibdata1,可以從 ibdata1 文件中提取數(shù)據(jù)。
1. 獲取表的 table id,sys_table 存有表的 table id,sys_table 表 index id 是1,所以從0000000000000001.page 獲取表 id./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000001.page -t dictionary/SYS_TABLES.sql | grep sakila/actor000000000B28 ?2A000001430D4D ?SYS_TABLES ?"sakila/actor" ?158 ?4 ?1 0 ? 0 ? "" ?0000000000B28 ?2A000001430D4D ?SYS_TABLES ?"sakila/actor" ?158 ?4 ?1 0 ? 0 ? "" ?0
2. 利用 table id 獲取表的主鍵 id,sys_indexes 存有表索引信息,innodb 索引組織表,找到主鍵 id 即找到數(shù)據(jù),sys_indexes 的 index id 是3,所以從0000000000000003.page 獲取主鍵 id
./c_parser -4Df pages-ibdata1/FIL_PAGE_INDEX/0000000000000003.page -t dictionary/SYS_INDEXES.sql | grep 158000000000B28 ? ?2A000001430BCA ?SYS_INDEXES ? ? 158 ? ? 376 ? ? "PRIMARY" ? ? ? 1 ? ? ? 3 ? ? ? 0 ? ? ? 4294967295000000000B28 ? ?2A000001430C3C ?SYS_INDEXES ? ? 158 ? ? 377 ? ? "idx_actor_last_name" ? ? ? ?1 ? ? ? 0 ? ? ? 0 ? ? ? 4294967295000000000B28 ? ?2A000001430BCA ?SYS_INDEXES ? ? 158 ? ? 376 ? ? "PRIMARY" ? ? ? 1 ? ? ? 3 ? ? ? 0 ? ? ? 4294967295000000000B28 ? ?2A000001430C3C ?SYS_INDEXES ? ? 158 ? ? 377 ? ? "idx_actor_last_name" ? ? ? ?1 ? ? ? 0 ? ? ? 0 ? ? ? 4294967295
3. 知道了主鍵 id,就可以從對(duì)應(yīng) page 中提取表數(shù)據(jù),并生成 sql 文件。
./c_parser -4f pages-ibdata1/FIL_PAGE_INDEX/0000000000000376.page -t sakila/actor.sql dumps/default/actor 2 dumps/default/actor_load.sql
4. 最后導(dǎo)入恢復(fù)的數(shù)據(jù)
cat dumps/default/*.sql | mysql sakila
更多詳細(xì)情況點(diǎn)擊網(wǎng)頁(yè)鏈接
請(qǐng)點(diǎn)擊輸入圖片描述
1
找個(gè)別的機(jī)器安裝個(gè)同版本的mysql或從已安裝同版本的其他機(jī)器上(非同版本的也可以試下):
拷貝
mysql/data/mysql
目錄到你的mysql/data/
下吧
2
試著啟動(dòng)mysql服務(wù),如果能啟動(dòng)了,理論上應(yīng)該丟失的只有用戶、授權(quán)等一些系統(tǒng)信息,不影響你的使用的數(shù)據(jù);
如果不能啟動(dòng),看錯(cuò)誤日志,爭(zhēng)取啟動(dòng)了。
3
趕緊把數(shù)據(jù)備份一份出來(lái),重新把所有庫(kù)(只是你后來(lái)創(chuàng)建的業(yè)務(wù)相關(guān)的庫(kù),不包括mysql庫(kù))都刪了,重新導(dǎo)入一遍。理論上不這樣也可以,但只是非生產(chǎn)重要的環(huán)境下。
4
重新做用戶授權(quán)。
情況1、如果你有該庫(kù)的整體備份或?qū)@個(gè)表的單獨(dú)備份,那么也許可以恢復(fù)??梢詫⒆钚碌膫浞莼謴?fù)到一個(gè)備用的服務(wù)器上,導(dǎo)出那表的內(nèi)容,完成恢復(fù)
情況2、如果沒(méi)有任何備份,那就基本沒(méi)戲了。一般刪除表的操作是drop table,日志中不會(huì)記錄刪除具體行數(shù)的記錄。表所對(duì)應(yīng)目錄下的文件已經(jīng)被刪除(innodb獨(dú)立表空間,單表歸為一文件)。同樣的情況適用于myisam數(shù)據(jù)庫(kù)引擎,對(duì)應(yīng)的myd/myi/frm文件均被刪除。這不像windows還有垃圾箱,是不可逆的操作
MySQL開啟binlog后,寫入操作都會(huì)記錄到二進(jìn)制日志里,可以使用mysqlbinlog查看/導(dǎo)出/恢復(fù)數(shù)據(jù).
假設(shè)你之前進(jìn)行了 mysqldump全量備份,和binlog增量備份(在mysqldump全量備份時(shí)使用參數(shù)--flush-logs清除全量備份前的binlog).
先恢復(fù)之前用mysqldump進(jìn)行的全量備份,然后用 mysqlbinlog進(jìn)行時(shí)間點(diǎn)還原: