mysql 5.7 删除ibdata1 、ib_logfile 文件的数据恢复
-
简介:
本文记录删除ibdata1 、ib_logfile 文件被意外删除且无法还原或损坏的解决方案,当删除后没有重启mysql 可以查询进程号,找到删除的文件可以还原回来。参考其他文章。本文介绍ibdata1 、ib_logfile 文件无法找到或异常没有备份的情况处理。
新安装一台mysql用作从库
注意安装版本与主库版本一致。
获取所有建表语句
如果原表所有建表语句都有保存最方便直接用即可。
如果没有保存需要使用工具mysqlfrm。在问题机器主库安装下:
#安装目录 自己创建 cd /data/ #下载文件 wget https://cdn.mysql.com/archives/mysql-utilities/mysql-utilities-1.6.5.tar.gz #解压文件 tar -xf mysql-utilities-1.6.5.tar.gz ls #进入解压好的文件夹 cd mysql-utilities-1.6.5/ #build构建 python ./setup.py build #install安装 python ./setup.py install #安装成功查看命令 mysqlfrm --version
- 模式介绍
–basedir:需指定服务器的基本目录,相当于再生一个数据库实例,还需指定prot,user及.frm文件位置等信息,指定的prot不能与在运行的数据库冲突,可在原数据库无法打开情况下使用,在读取.frm文件后,再生的实例将被关闭,所有的临时文件将被删除。
例:mysqlfrm --basedir=/mysql/mysqld/ --port=3333 --user=mysql /mysql/data/test/tables.frm --show-stats
–server:需指定数据库的连接字符串,需在原数据库可以打开的情况下使用,指定数据库用户名,密码,端口号及.frm文件位置等信息。
例:mysqlfrm --server=root:Root#123@localhost:3306 /mysql/data/test/tables.frm --port=3310 --user=mysql
注意:如数据库还可以正常连接,推荐使用–server模式
- 获取建表语句脚本
#!/bin/bash # 定义变量 output_file="Create.sql" # 输出文件名 mysql_root_password="123456" # MySQL root 用户密码 mysql_host="localhost" # MySQL 主机 mysql_port="3306" # MySQL 端口 mysql_user="mysql" # MySQL 用户名 data_dir="/data/mysql/" # MySQL 数据目录 excluded_dirs=(mysql sys performance_schema) # 需要排除的目录列表 # 清空输出文件,如果文件不存在则创建 > $output_file # 构建排除目录的 find 过滤条件 exclude_find="" for dir in "${excluded_dirs[@]}"; do exclude_find+=" -path ${data_dir}${dir} -o" done exclude_find=${exclude_find::-2} # 去掉最后一个 "-o" # 查找所有的 .frm 文件,排除指定目录 find $data_dir -type d \( $exclude_find \) -prune -o -type f -name '*.frm' -print | while read frm_file; do # 提取建表语句(去掉注释) mysqlfrm --server=root:"$mysql_root_password"@$mysql_host:"$mysql_port" "$frm_file" --user=$mysql_user \ | grep -v '^#' >> $output_file echo -e "\n" >> $output_file # 添加换行符便于分隔 done echo "建表语句已保存到 $output_file"
建表语句导入从库
从库先创建所有主库的库,执行Create.sql语句。
还原数据
修改从库配置文件添加:innodb_force_recovery=1,重启数据库。
建表语句创建好后,对每个表进行删除表空间,注意脚本不要放mysql默认4个库,脚本如下:
#!/bin/bash # MySQL 用户名和密码 MYSQL_USER="root" MYSQL_PASS="123456" # 数据库列表 databases=( "aaa" "bbbb" "ccc" "ddd" ) # 遍历数据库列表 for db in "${databases[@]}"; do echo "Processing database: $db" # 获取当前数据库中的所有表 tables=$(mysql -u $MYSQL_USER -p"$MYSQL_PASS" -e "SHOW TABLES;" $db | awk '{print $1}' | grep -v '^Tables_in') # 遍历表列表并执行 DISCARD TABLESPACE for table in $tables; do echo "Discarding tablespace for table: $table in database: $db" mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table DISCARD TABLESPACE;" $db done done echo "Tablespace discard operation completed."
执行完删除表空间后导入主库的ibd文件。库很多可以使用脚本主库打包mysql目录放到从库中,使用脚本复制:
#!/bin/bash # 源目录和目标目录 src_dir="/home/mysqlbak" dest_dir="/home/mysql" # 目录列表 dirs=( "aaa" "bbb" ) # 遍历目录列表并复制文件 for dir in "${dirs[@]}"; do src_path="$src_dir/$dir" dest_path="$dest_dir/$dir" # 检查源目录是否存在 if [ -d "$src_path" ]; then # 复制 .ibd 文件 if [ "$(ls -A $src_path/*.ibd 2>/dev/null)" ]; then echo "Copying .ibd files from $src_path to $dest_path" # 创建目标目录(如果存在) if [ ! -d "$dest_path" ]; then echo "Directory $dest_path does not exist. Skipping copy." continue fi cp -a "$src_path"/*.ibd "$dest_path/" else echo "No .ibd files found in $src_path" fi else echo "Source directory $src_path does not exist" fi done echo "File copy operation completed."
再次执行导入表空间命令,脚本和删除表空间基本一样,复制一份修改一个地方即可:
mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table DISCARD TABLESPACE;" $db ##改为 mysql -u $MYSQL_USER -p$MYSQL_PASS -e "ALTER TABLE $table IMPORT TABLESPACE;" $db
大功告成!检测从库数据是否恢复。
数据恢复后注意修改配置文件:innodb_force_recovery=1 删除,重启数据库。