mysql根据.frm和.ibd文件恢复表结构和数据的具体代码实现,能够批量恢复数据

本文是为了让这篇博客 https://blog.csdn.net/hzw19920329/article/details/78045864 能够进行半自动的实现数据恢复。让恢复速度快起来


package com.mysql.data.recover;

import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * mysql根据.frm和.ibd文件恢复表结构和数据
 * @author Administrator
 *
 */
public class MysqlDataRecover {

	final static String databaseName = "marrys"; 
	/**
	 * 1、先创建对应的表,至于具体有多少个列及各个列的消息消息先不用管,同一创建为包含列a的表。
	 * @throws Exception
	 */
	public static void firstCreateTempTable() throws Exception {
		
		List<String> tables = getAllTables();
		for (String table : tables) {
			String c = "create table "+table;
			c += "( a int );";
			System.out.println(c);
		}
	}
	
	/**
	 * 2、创建完成后,将数据库关闭,将所有的.frm文件移动备份都某个文件夹中去。
	 *    将你想要还原的表中的所有.frm文件移动到此数据库中来。
	 *    在my.ini或者my.cnf文件中添加如下配置: innodb_force_recovery = 6
	 *    然后重启数据库
	 */
	
	/**
	 * 3、分析错误日志文件
	 * 错误日志文件一般会有如下的错误日志输出: 
	 * [Warning] InnoDB: table marry/rc_marry contains 1 user defined columns in InnoDB, but 88 columns in MySQL. Please check INFORMATION_SCHEMA.INNODB_SYS_COLUMNS and http://dev.mysql.com/doc/refman/5.6/en/innodb-troubleshooting.html for how to resolve it
	 * 具体信息解释为:  数据库下面的rc_marry表定义只有1个列(见第一步),然而在.frm中有88个列。
	 * 从这里我们可以得到信息是:  rc_marry表有88个列。
	 * 故我们通过这个错误信息又去创建相同表,而且此表有88个列,具体各个列的信息依旧不用关心。列数匹配即可。
	 * 这里输出的sql是先删除,在创建表。
	 * 需要将第二步骤的备份文件恢复回来,否则将会导致无法执行删除操作。
	 * 在my.ini或者my.cnf文件中注释如下配置: #innodb_force_recovery = 6
	 * @throws Exception
	 */
	public static void errorLogParseCreateTables() throws Exception {
		
		Map<String,Integer> tables = getTableColumnsNum();
		for (Entry<String, Integer> table : tables.entrySet()) {
			
			String c = "drop table if exists "+table.getKey()+";\n";
			c += "create table "+table.getKey();
			c+= "( ";
			for (int i = 0; i < table.getValue(); i++) {
				c+= "a"+i+" int,";
			}
			c = c.substring(0, c.length()-1);
			c+="  );";
			System.out.println(c);
		}
	}
	
	/**
	 *  4、经过上面三个步骤,我们可以通过navcat工具将完整的表结构信息导出来,或者通过sql语句。
	 *    然后在重新执行导出的语句,到此为止就算是将数据库结构ddl表结构恢复了。
	 */
	public static void showCreateTables() throws Exception {
		
		//通过navcat自己导出表结构即可。
	}
	
	/**
	 *  5、解除所有表的.ibd文件与.frm文件绑定
	 * 
	 */
	//.ibd文件与原先的.frm文件解除绑定
	public static void discardTablespace() throws Exception {
		
		List<String> tables = getAllTables();
		for (String table : tables) {
			String c = "alter table "+table+" discard tablespace;";
			System.out.println(c);
		}
		
	}
	/**
	 *  6、将需要恢复的表的.ibd文件拷贝到数据库文件中,
	 *    然后在重新执行绑定即恢复了数据
	 */
	//.ibd文件与原先的.frm文件解除绑定
	public static void importTablespace() throws Exception {
		
		List<String> tables = getAllTables();
		for (String table : tables) {
			String c = "alter table "+table+" import  tablespace;";
			System.out.println(c);
		}
		
	}
	
	
	
	

	/**
	 * 提取表名称和表具体字段数量的正则表达式
	 */
	final static String getTableNameAndColumnsNum = ".*table "+databaseName+"/(\\S+) contains 1 user defined columns in InnoDB, but (\\d+) columns in MySQL. Please check INFORMATION_SCHEMA.INNODB_SYS_COLUMNS.*"; 
	/**
	 * 通过具体的错误日志提取表名称及表的列数量
	 * @return
	 * @throws Exception
	 */
	private static Map<String, Integer> getTableColumnsNum() throws Exception {
		
		List<String> tables = getAllTables();
		BufferedReader reader = new BufferedReader(new FileReader("F:\\pdy\\path\\pdyerror.log"));
		String line = null;
		Map<String, Integer> result = new HashMap<>();
		try {
			while ((line = reader.readLine()) != null) {
				
				if(line.matches(getTableNameAndColumnsNum)) {
					Matcher m = Pattern.compile(getTableNameAndColumnsNum).matcher(line);
					while(m.find()) {
						String table = m.group(1);
						String cloumns = m.group(2);
						if(tables.contains(table)) {
							result.put(table, Integer.parseInt(cloumns));
						}
					}
				}
			}
		} finally {
			reader.close();
		}
		return result;
	
	}

	private static List<String> getAllTables() throws Exception {
		
		BufferedReader reader = new BufferedReader(new FileReader("F:\\pdy\\path\\ta.txt"));
		String line = null;
		
		List<String> frm = new ArrayList<String>();
		try {
			while ((line = reader.readLine()) != null) {
				
				String[] ss = line.split("\\s+");
				for (String s : ss) {
					if(s.endsWith(".frm")) {
//						System.out.println(s);
						frm.add(s.substring(0, s.length()-4));
					}
				}
			}
		} finally {
			reader.close();
		}
		return frm;
	}
	private static List<String> getAllTables(String path) throws Exception {
		
		BufferedReader reader = new BufferedReader(new FileReader(path));
		String line = null;
		
		List<String> frm = new ArrayList<String>();
		try {
			while ((line = reader.readLine()) != null) {
				
				String[] ss = line.split("\\s+");
				for (String s : ss) {
					if(s.endsWith(".frm")) {
//						System.out.println(s);
						frm.add(s.substring(0, s.length()-4));
					}
				}
			}
		} finally {
			reader.close();
		}
		return frm;
	}
	
	public static void main(String[] args) throws Exception {
		List<String> s = getAllTables();
		List<String> ss = getAllTables("F:\\pdy\\path\\pdy.log");
		for (String table : ss) {
			if(!s.contains(table)) {
				System.out.println("drop talbe "+table+";");
			}
		}
//		firstCreateTempTable();
//		errorLogParseCreateTables();

//		discardTablespace();
//		importTablespace();
	}
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值