java远程数据库备份_Java程序实现oracle远程数据库的备份和恢复

最近项目到了收尾的阶段,为了使我们的系统功能更加完成,也为了使客户更加安心,决定添加一个oracle备份和还原的功能。现做一下分享。

一、导入导出命令

oracle备份和还原除了使用工具比如PL/SQL进行导出导入还可以利用命令,在程序中也就只能调用外部命令了,首先我们得知晓oracle备份和还原的命令,根据需要我是需要备份和还原项目数据库的所有的表的,以下命令为备份和还原所有表命令。

备份:exp username/password@TEST file=D:\export.dmp

还原:imp username/password@TEST file=D:\export.dmp full=y ignore=y

二、Java代码实现

调用runtime方法,因为是远程的数据库,所以SID为ip+"/"+数据库名

/**

* 实现Oracle数据库导出

* @author weiwenwen

* userName 进入数据库所需要的用户名

* password 进入数据库所需要的密码

* SID 用户所在的数据库名

* avePath 数据库导出文件保存路径

* fileName 数据库导出文件文件名

* @return 返回0表示导出成功

* @throws Exception

*/

public int oraBackup() throws IOException{

//读取配置文件配置项

String userName=Global.getConfig("jdbc.username");

String password=Global.getConfig("jdbc.password");

String savePath=Global.getConfig("oraBackupPath");

String SID=Global.getConfig("SID");

String id=IdGen.uuid();

File saveFile = new File(savePath);

if (!saveFile.exists()) {// 如果目录不存在

saveFile.mkdirs();// 创建文件夹

}

//将记录插入数据库

PageData pd=new PageData();

pd.put("id", id);

pd.put("user_name", UserUtils.getUser().getName());

pd.put("op_dt", new Date());

oracleBackupDao.insertOraBackup(pd);

//所有空表

List tablesList=oracleBackupDao.findAltTables();

//为所有空表执行语句

for (int i = 0; i < tablesList.size(); i++) {

oracleBackupDao.doAltSql(tablesList.get(i));

}

String command ="exp " + userName + "/" + password + "@" + SID + " file=" + savePath + id + ".dmp";

System.out.println("备份数据库命令操作:" + command);

Process process = Runtime.getRuntime().exec(command);

final InputStream is1 = process.getInputStream();

new Thread(new Runnable() {

public void run() {

BufferedReader br = new BufferedReader(new InputStreamReader(is1));

String info;

try {

while ((info=br.readLine()) != null){

System.out.println("info: "+info);

}

} catch (IOException e) {

e.printStackTrace();

}

}

}).start(); // 启动单独的线程来清空process.getInputStream()的缓冲区

InputStream is2 = process.getErrorStream();

BufferedReader br2 = new BufferedReader(new InputStreamReader(is2));

// 保存输出结果

StringBuilder buf = new StringBuilder();

String line = null;

int i=0;

while ((line = br2.readLine()) != null){

// 循环等待ffmpeg进程结束

System.out.println("info: " +line);

buf.append(line);

}

try {

if(buf.toString().contains("ORA-")&&buf.toString().contains("EXP-")){

System.err.println("备份失败!");

process.destroy();

}else{

i=process.waitFor();

System.out.println("over status: "+i);

}

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("备份结束...");

//备份完成将文件大小更新到表,备份的文件路径

String dmpPath = savePath + id + ".dmp";

//获取文件大小

pd.put("file_size", new File(dmpPath).length());

oracleBackupDao.updateFileSize(pd);

return 0;

}

PS:因为是oracle11g,发现11G中新特性,当表无数据时,不分配segment,以节省空间。而使用exp命令时,无Segment的表不会被导出。所以如果单纯直接执行导出语句是不可以的,必须查询所有的空表后,执行alter命令。

select table_name from user_tables where NUM_ROWS=0;

如果平时导出的话直接执行这句:

select 'alter table '||table_name||' allocate extent;' from user_tables where num_rows=0

最后为所有的表执行alter命令

alter table '表名' allocate extent;

导入还原的代码是类似的,根据命令自己拼字符串即可,不再累述

小结:

1.看似一个小的功能,当简单代码的完成后的测试更是重头戏,要考虑表是不是全部导出,每个表的数据是不是完全,要考虑备份导出过程中的突发情况,比如网线断连接。

2.导入还原时添加full=y ignore=y,否则导入会报错

3.如果原数据库是有数据的直接导入的话数据会在原基础上添加,所以可能存在数据重复现象,试了很多办法不可以,所以我的处理是在还原时查询所有表,用truncate强制执行清表的操作,再重新导入。

你可能感兴趣的:(java远程数据库备份)