Mysql 使用ibd数据文件进行数据恢复 (以及数据移动) 1067的解决办法

本文详细介绍了如何将 MySQL 数据库从 C 盘迁移到其他分区,并提供了遇到 1067 错误时的解决方案。此外,还分享了使用 IBD 文件进行数据恢复的具体步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

使用过数据库的哥们都知道,最开始我们不小心把数据库安装到c盘,当时忘记设置了数据路径,导致数据默认也放在c盘,随着时间的推移,数据库数据越来越大,导致c盘空间不够了。

于是乎我们开始研究怎么样移动数据,当然简单的步骤莫过于下:

(1)停止mysql服务。(运行services.msc)

(2)打开my.ini文件,该文件有可能不在安装程序的目录下,而在数据目录下,不同的mysql版本大概不同吧。

比如我安装的5.7.3,默认在数据文件目录programData(该目录竟然是隐藏的!需要打开文件夹设置显示隐藏文件)中的mysql目录中。(该版本好像现在下载不到了,不知道是什么原因,如果你需要可以留个邮箱)

修改my.ini中的datadir="F:\mysql\data\"。修改成你需要移动数据到的位置。然后就把你原来数据文件中的整个data目录移动到目标位置。当然要和你设置的完全相同,切记要细心。

(3)保存my.ini之后启动mysql服务,应该就可以了。(该my.ini文件千万不要移动你新的数据位置,否则就是灾难的开始!!)


通过以上步骤,很容易让人觉得,mysql的数据文件就放在对应的数据库文件夹下,然后只需要复制移动数据文件,就可以完成数据的转移(如复制到另外一台机器)和数据恢复。可这样是完全不可以的。你移动了数据文件,在mysql中是可以表存在,可惜你就是打呀打不开,很是郁闷的。还会莫名的导致1067错误!!当然面对1067网上有很多种解决办法,靠谱的好像就一个,那就是删除那三个文件,ib_logfile0、ib_logfile1、ibdata1(记得先停止mysql服务),然后重新启动mysql。

当然,删除了这三个文件,也就意味着你已经删除了你数据库中所有的数据,不信?你可以在mysql中看到表存在,可惜,你就是打不开!面对这种情况,就应该使用ibd文件进行恢复了。当然你如果有数据库的批量插入语句备份就最好了。直接再导入一遍就可以(我指的是工具是SQLyog,里面有从外部sql文件中导入的功能。)

具体的方法我参考的是:http://www.linuxidc.com/Linux/2014-07/104434.htm

先将数据文件frm和ibd文件进行移动保存。

具体表结构的恢复好像不是很靠谱,其实可以直接用文本打开数据文件夹下的frm文件,里面有表结构的信息,直接复制出来,然后创建一个表就可以了。(创建时先把frm从目录中移动出来,否则你在创建的时候会提示该表已经存在),创建表的时候,他会自动的生成一个同名的frm和ibd文件。

最关键的就是ibd文件的使用。首先得把你需要用到的ibd文件进行复制备份到一个地方。(其实这一步应该在上一步之前)。

a、建立一个数据库,根据上面导出的创建表的sql执行创建表。(表已经创建好了就不用了)

b、找到记录点。先要把当前数据库的表空间废弃掉,使当前ibd的数据文件和frm分离。  ALTER TABLE test DISCARD TABLESPACE;

test是你的表名

c、把之前要恢复的 .ibd文件复制到新的表结构文件夹下。 使当前的ibd 和frm发生关系。ALTER TABLE test  IMPORT TABLESPACE;

(这个过程需要一点时间,就和数据导入是差不多,其实本质上就是那三个文件和你的数据发生某种关联,具体不知道,还望指点)

d、将恢复好的数据导出就行了(这一步相当关键,经过上述动作你是可以完整的看到数据了,但是第二天你再来看,你又会遇到1067,所以趁着可以用的机会,赶紧导出备份一次!!)


总的来说,ib_logfile0、ib_logfile1、ibdata1这三个文件和my.ini,以及你的数据文件是紧密联系在一起的,哪一个出现意外情况,导致不一致,就会出现1067,所以操作需谨慎!!不过你只要记得备份你的数据成sql语句,那什么都不用害怕了!


### 使用 MySQL IBD 文件进行表空间或数据恢复的最佳实践 #### 方法概述 当需要通过 `.ibd` 文件恢复 MySQL 表的空间或数据时,可以按照以下方法操作。此过程涉及多个步骤,包括创建数据库架构、丢弃和重新导入表空间以及调整文件权限。 --- #### 步骤说明 1. **创建目标数据库 Schema** 需要先确保目标数据库已经存在并具有相同的结构。如果没有现成的建表语句,则可以通过解析 `ibdata` 或其他方式获取 DDL 信息[^2]。 ```sql CREATE DATABASE IF NOT EXISTS target_database; USE target_database; ``` 2. **重建表结构** 如果原始表定义仍然可用,则可以直接执行相应的建表语句;否则可能需要手动重构这些表的定义或者尝试从元数据中提取它们的信息[^3]。 3. **丢弃现有表空间** 对于每一个待恢复的表,在其上运行如下 SQL 命令来释放当前关联的存储引擎实例: ```sql ALTER TABLE table_name DISCARD TABLESPACE; ``` 4. **复制原生 .ibd 文件至适当位置** 将备份中的实际物理磁盘映像拷贝回默认路径下的相应子目录里去替换掉旧版本的那个副本,并确认所属关系正确无误以便后续加载动作能够顺利开展下去: ```bash cp /path/to/backup/table_name.ibd /var/lib/mysql/target_database/ chown mysql:mysql /var/lib/mysql/target_database/table_name.ibd ``` 5. **重载外部链接资源** 完成了前面几步之后就可以再次调用下面这条指令让系统重新认识这个已经被更改过的对象了——即把之前分离出去的部分接回来形成完整的整体视图供查询使用等功能正常运作起来啦! ```sql ALTER TABLE table_name IMPORT TABLESPACE; ``` 上述流程完成后应该就能看到预期效果咯~不过需要注意的是整个过程中涉及到的操作都比较敏感所以一定要小心谨慎行事哦😊 --- ### 注意事项 - 确认源环境和服务端配置参数一致比如字符集编码等细节方面的东西不然可能会引起兼容性问题导致失败告警提示出来呢❌; - 备份前最好关闭自动提交模式以免中途被打断造成不必要的麻烦😅; - 不同操作系统之间可能存在细微差异所以在移植跨平台项目的时候记得查阅官方文档了解更多相关内容吧📚。 ```python # 示例 Python 脚本用于自动化部分任务 (可选) import os import subprocess def restore_ibd(database, table, backup_path): # Step 1: Create database and use it create_db_cmd = f"CREATE DATABASE IF NOT EXISTS {database};" execute_sql(create_db_cmd) # Step 2: Discard tablespace discard_cmd = f"ALTER TABLE `{table}` DISCARD TABLESPACE;" execute_sql(discard_cmd) # Step 3: Copy .ibd file to correct location ibd_file = f"{backup_path}/{table}.ibd" dest_dir = f"/var/lib/mysql/{database}/" copy_command = ["cp", ibd_file, dest_dir] change_owner_command = ["chown", "mysql:mysql", f"{dest_dir}{table}.ibd"] run_shell(copy_command) run_shell(change_owner_command) # Step 4: Import tablespace back into the system import_cmd = f"ALTER TABLE `{table}` IMPORT TABLESPACE;" execute_sql(import_cmd) def execute_sql(query): """Executes given SQL query.""" command = ['mysql', '-uroot', '-e', query] result = subprocess.run(command, capture_output=True, text=True) if result.returncode != 0: raise Exception(f"Error executing SQL: {result.stderr}") def run_shell(cmd_list): """Runs shell commands provided as a list of strings.""" process = subprocess.Popen(cmd_list, stdout=subprocess.PIPE, stderr=subprocess.PIPE) output, error = process.communicate() if process.returncode != 0: raise Exception(f"Shell Command Failed with Error:\n{error.decode('utf-8')}") ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小田田_XOW

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值