在想清楚解决方案、做好全部备份、逐个相关文件关系查验之前,尽量不要做任何文件的写入、覆盖操作。
记一段辛酸但好歹不用跳天台的数据库恢复笔记
能写一个自动备份脚本,为什么要偷几十秒的懒呢?
主要也是参考下面链接最终成功恢复。 这篇文章的步骤稍微有点多。有些是恢复不必要的,这里做一下自己的整理。
如何在删除ibdata1的情况下恢复
数据库宕机恢复数据或迁移数据,几个重要节点。
1 检查数据库目录配置是否正确
数据库目录配置错误时,MySQL是不能正常启动的,报错可能与此无关。 比如说,找不到 user_table这样的报错,都可能是目录配置错误。
2 拷贝每一个数据库数据文件夹内的文件到安全位置
在进行迁移,覆盖、写入等操作的时候,一定要提前把相关文件夹的内容做好备份。 譬如说,我在修改数据库目录的时候,点击了宝塔面板的迁移按钮,导致ibdata1文件被覆盖,以及随之而来的崩溃恢复之旅。 如果提前做好了备份,可能几秒钟就可以顺利恢复了。
3 检查ibdata1的最后更新日期,以及是否可用
MySQL在运行以及关闭时会更新ibdata1文件,我们通过ibdata1的最后更新时间可以判断这个文件大概是什么时候的。 如果是比较新的,一定要备份好,因为可能会在关键的时候救一命。
4 丢失ibdata1或 ibdata1文件损坏,与数据库数据文件不匹配时的数据恢复。
由于innoDB将表数据字典存储在ibdata1中,当ibdata1改变时,ID就无法对应上,所以就会找不到表
解决方案概括来说就是
代码语言:javascript复制CREATE TABLE table_name ...; # 这里的表格式 必须和之前的严格一致,否则会造成数据乱码
ALTER TABLE table_name DISCARD TABLESPACE; # 去除表空间( 会删除 table_name.idb )
# 复制原数据 table_name.idb 到数据目录下 ( 这一步建议先停止MySQL服务器,复制完成再开启 )
ALTER TABLE table_name IMPORT TABLESPACE; # 导入表空间
# DISCARD TABLESPACE 相当于清空新表数据
# IMPORT TABLESPACE 相当于从文件导入数据
小技巧和经验
在没有有效ibdata1的时候,其实可以放弃一键恢复的想法了,这时候要做的就是在数据库正常建立数据库、数据表。
建立完数据表的时候,使用discard...命令删除表空间
这时候即可批量进行,也可以单个表进行,(不用再理会ibdata1文件了)
譬如说,批量恢复了20张表,其中有2个有乱码。 那么可以使用DROP命令删除这个表,(换一下字段格式)重新建立这个表,然后重复 DISCARD, 复制table.idb文件,IMPORT 命令,测试是否找到正确格式。
这里需要跳过MySQL输密码的步骤,所以需要在mysql设置里面 为root用户设置好密码,这样可以直接登录。
代码语言:javascript复制DROP TABLE item_unit;
CREATE TABLE IF NOT EXISTS item_unit (
id INT(15) NOT NULL AUTO_INCREMENT COMMENT '序列ID' ,
PRIMARY KEY (id)
) ENGINE InnoDB CHARSET utf8mb4 COLLATE utf8mb4_general_ci;
ALTER TABLE item_unit DISCARD TABLESPACE;
exit;
cp /mnt/mysql_backup/traper/item_unit.ibd /mnt/mysql/traper/item_unit.ibd
chown mysql /mnt/mysql/traper/item_unit.ibd
mysql;
use traper;
ALTER TABLE item_unit IMPORT TABLESPACE;