十年网站开发经验 + 多家企业客户 + 靠谱的建站团队
量身定制 + 运营维护+专业推广+无忧售后,网站问题一站解决
每个 DBA 是不是都有过删库的经历?删库了没有备份怎么办?备份恢复后无法启动服务什么情况?表定义损坏数据无法读取怎么办?
十多年的兴业网站建设经验,针对设计、前端、开发、售后、文案、推广等六对一服务,响应快,48小时及时工作处理。网络营销推广的优势是能够根据用户设备显示端的尺寸不同,自动调整兴业建站的显示方式,使网站能够适用不同显示终端,在浏览器中调整网站的宽度,无论在任何一种浏览器上浏览网站,都能展现优雅布局与设计,从而大程度地提升浏览体验。创新互联建站从事“兴业网站设计”,“兴业网站推广”以来,每个客户项目都认真落实执行。
我曾遇到某初创互联网企业,因维护人员不规范的备份恢复操作,导致系统表空间文件被初始化,上万张表无法读取,花了数小时才抢救回来。
当你发现数据无法读取时,也许并非数据丢失了,可能是 DBMS 找不到描述数据的信息。
背景
先来了解下几张关键的 InnoDB 数据字典表,它们保存了部分表定义信息,在我们恢复表结构时需要用到。
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对应 `ID` bigint(20) unsigned NOT NULL DEFAULT '0', 索引id `NAME` varchar(120) DEFAULT NULL, 索引名称 `N_FIELDS` int(10) unsigned DEFAULT NULL, 索引包含字段的个数 `TYPE` int(10) unsigned DEFAULT NULL, `SPACE` int(10) unsigned DEFAULT NULL, 存储索引的表空间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对应 `POS` int(10) unsigned NOT NULL, 字段相对位置 `NAME` varchar(255) DEFAULT NULL, 字段名称 `MTYPE` int(10) unsigned DEFAULT NULL, 字段编码 `PRTYPE` int(10) unsigned DEFAULT NULL, 字段校验类型 `LEN` int(10) unsigned DEFAULT NULL, 字段字节长度 `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 文件定义了每个字典表的 index id,对应 id 的 page 中存储着字典表的数据。
这里我们需要借助 undrop-for-innodb 工具恢复数据,它能读取表空间信息得到 page,将数据从 page 中提取出来。
# wget yum install -y gcc flex bison# make# make sys_parser
# ./sys_parser 读取表结构信息
sys_parser [-h] [-u] [-p] [-d] databases/table
stream_parser 读取 InnoDB page 从 ibdata1 或 ibd 或分区表
# ./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
接下来,我们演示场景的几种数据恢复场景。
场景1:drop table
是否启用了 innodb_file_per_table 其恢复方法有所差异,当发生误删表时,应尽快停止MySQL服务,不要启动。若 innodb_file_per_table=ON,最好只读方式重新挂载文件系统,防止其他进程写入数据覆盖之前块设备的数据。
如果评估记录是否被覆盖,可以表中某些记录的作为关键字看是否能从 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
首先恢复表结构信息1. 解析系统表空间获取 page 信息
./stream_parser -f /var/lib/mysql/ibdata1
2. 新建一个 schema,把系统字典表的 DDL 导入
cat dictionary/SYS_* | mysql recovered
3. 创建恢复目录
mkdir -p dumps/default
4. 解析系统表空间包含的字典表信息,
./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. 导入恢复的数据字典
cat dumps/default/*.sql | mysql recovered
6. 读取恢复后的表结构信息
./sys_parser -pmsandbox -d recovered sakila/actor
由于 5.x 版本 innodb 引擎并非完整记录表结构信息,会丢失 AUTO_INCREMENT 属性、二级索引和外键约束, DECIMAL 精度等信息。
若是 mysql 5.5 版本 frm 文件被从系统删除,在原目录下 touch 与原表名相同的 frm 文件,还能读取表结构信息和数据。若只有 frm 文件,想要获得表结构信息,可使用 mysqlfrm --diagnostic /path/to/xxx.frm,连接 mysql 会显示字符集信息。
innodb_file_per_table=OFF
因为是共享表空间模式,数据页都存储在 ibdata1,可以从 ibdata1 文件中提取数据。
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 即找到数据,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,就可以从对应 page 中提取表数据,并生成 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. 最后导入恢复的数据
cat dumps/default/*.sql | mysql sakila
更多详细情况点击
网页链接
请点击输入图片描述
首先要确定你的mysql服务是关闭的状态,不然卸载不干净,在我的电脑(计算机)一 管理 一 服务和应用程序 一 服务,找到mysql 把状态关闭
一、在控制面板中卸载mysql软件
二、卸载过后删除C:Program Files (x86)MySQL该目录下剩余了所有文件,把mysql文件夹也删了
三、windows+R运行“regedit”文件,打开注册表
四、删除注册表:HKEY_LOCAL_MACHINESYSTEMControlSet001ServicesEventlogApplicationMySQL文件夹
然后退出程序重启电脑就可以了。
说明之前你没有卸载干净,mysql卸载的时候一定要用它自己的卸载工具,
然后在用其他工具对注册表进行删除,这样子之后就可以了
你之前装过了就会有一个MySQL的服务,现在你重新装它就提示你MySQL这个服务已经存在了,你可以取别的名字作为MysQL服务,也可以把之前的MysQL服务卸载掉。怎么卸载?先停止服务:netstopmysqlc:\mysql\bin\mysqld.exe-remove控制面板和安装目录中删除重启,删除安装目录残余的信息
一般情况下很多软件卸载完还是有残余的,想你说的这种情况建议你在注册表中删除所有和mysql有关的信息
,或者是直接将服务停止即可
可能没卸载干净。。。在安装mysql数据库时,如果重新安装,很容易遇见apply security setting error,即在配置mysql启动服务时,在启动apply security setting时会出错,原因是卸载mysql时并没有完全删除文件,所以有必要手动清除这些,要清除的文件主要:
一、mysql的安装目录,一般为C:\Program Files目录下。
二、mysql的数据存放目录,一般在C:\Documents and Settings\All Users\Application Data目录下(需要注意的时Application Data这个文件夹默认是隐藏的,要通过 工具-文件夹选项-查看-显示所有文件与文件夹 来设置隐藏文件可见)。
三、删除注册表数据,通过regedit,删除以下几个文件:
引用
HKEY_LOCAL_MACHINE/SYSTEM/ControlSet001/Services/Eventlog/Applications/MySQL
HKEY_LOCAL_MACHINE/SYSTEM/ControlSet002/Services/Eventlog/Applications/MySQL
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Eventlog/Applications/MySQL
我试验成功过,你试试。