oracle創建Javasource實現數據庫備份


 

因客戶需求,需要在業務系統中,菜單中的網頁中的按鈕中加入一個按鈕,用於點擊備份數據庫

(環境:只配置了數據源連接oralce ,應用服務器和數據服務器不在一台機器,且數據庫機器oracle操作系統賬號密碼不知道無法遠程登陸機器進行備份,)

思索許久實現思路如下:

第一步:編寫一個java小程序,用於執行傳入的備份命令,如expdp ls 等,

第二步:創建javasource 用於執行備份命令。

第三步:創建過程用於調用Java source。

 

創建java測試類如下:

 
         

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
public class Test
{
public static String list_cmd(String str){
Runtime runtime=Runtime.getRuntime();
StringBuffer enco = new StringBuffer();
enco.append("GBK");
try{
Process proc =runtime.exec(str);
InputStream inp_suc=proc.getInputStream();
InputStream inp_err=proc.getErrorStream();
BufferedReader bfr_err = new BufferedReader(new InputStreamReader(inp_err,enco.toString()));
BufferedReader bfr_suc = new BufferedReader(new InputStreamReader(inp_suc,enco.toString()));
String strLine;
while( (strLine=(bfr_suc.readLine())) != null){

System.out.println(strLine);
}
while( (strLine=(bfr_err.readLine())) != null){

System.out.println(strLine);
}
proc.destroy();
inp_suc.close();
inp_err.close();
}catch (Exception e) {
System.out.println("EXECUTE IS ERROR!");
System.out.println(e.getMessage());
}
return "";
}

public static void main(String[] args){

list_cmd(args[0]);
}
}

 

測試java類運行輸出

 

創建用戶測試

  SQL> conn / as sysdba
  已連接。
  

  SQL> create user wx identified by 123;


用戶已創建。

SQL> grant  dba  to wx;

授權成功。

SQL>

 

 將java 類改裝成創建javasource語法,如下:(將測試的main方法注釋掉)

 

 

create or replace and compile java source named exe_linux as
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.UnknownHostException;
public class Test
{
  public  static  String list_cmd(String str){
     Runtime runtime=Runtime.getRuntime();
    StringBuffer  enco  =  new  StringBuffer(); 
    enco.append("GBK");
    try{
    Process proc =runtime.exec(str);
    InputStream inp_suc=proc.getInputStream();
    InputStream inp_err=proc.getErrorStream();
    BufferedReader bfr_err = new BufferedReader(new InputStreamReader(inp_err,enco.toString()));
    BufferedReader bfr_suc = new BufferedReader(new InputStreamReader(inp_suc,enco.toString()));
     String strLine;
        while( (strLine=(bfr_suc.readLine())) != null){
       
       System.out.println(strLine);
           }
    while( (strLine=(bfr_err.readLine())) != null){
       
      System.out.println(strLine);
     }
         proc.destroy();
         inp_suc.close();
         inp_err.close();
     }catch (Exception e) {
        System.out.println("EXECUTE IS ERROR!");
        System.out.println(e.getMessage());
      }
     return "";
    }
      
    /*  public static void main(String[] args){
      
        list_cmd(args[0]);
      }
      **/
}

/

 

使用sqlplus  連接oracle 數據庫

創建Javasource  

SQL> create or replace and compile java source named exe_linux as
  2  import java.io.BufferedReader;
  3  import java.io.InputStream;
  4  import java.io.InputStreamReader;
  5  import java.net.UnknownHostException;
  6  public class Test
  7  {
  8    public  static  String list_cmd(String str){
  9   Runtime runtime=Runtime.getRuntime();
 10      StringBuffer  enco  =  new  StringBuffer();
 11      enco.append("GBK");
 12      try{
 13      Process proc =runtime.exec(str);
 14      InputStream inp_suc=proc.getInputStream();
 15      InputStream inp_err=proc.getErrorStream();
 16      BufferedReader bfr_err = new BufferedReader(new InputStreamReader(inp_err,enco.toString()));
 17      BufferedReader bfr_suc = new BufferedReader(new InputStreamReader(inp_suc,enco.toString()));
 18       String strLine;
 19          while( (strLine=(bfr_suc.readLine())) != null){
 20
 21         System.out.println(strLine);
 22             }
 23      while( (strLine=(bfr_err.readLine())) != null){
 24
 25        System.out.println(strLine);
 26       }
 27           proc.destroy();
 28           inp_suc.close();
 29           inp_err.close();
 30       }catch (Exception e) {
 31          System.out.println("EXECUTE IS ERROR!");
 32          System.out.println(e.getMessage());
 33        }
 34       return "";
 35  }
 36
 37  /*  public static void main(String[] args){
 38
 39  list_cmd(args[0]);
 40    }
 41    **/
 42  }
 43
 44  /

Java 已創建。

 

創建存儲過程,(執行過程,傳參數給Javasource)

 

create or replace procedure p_exe_linux(str varchar2) as language java
name 'Test.list_cmd(java.lang.String)';
/

 

SQL中創建如下

 

SQL> create or replace procedure p_exe_linux(str varchar2) as language java
  2  name 'Test.list_cmd(java.lang.String)';
  3  /

過程已創建。

 

執行測試,

 

SQL> SET SERVEROUTPUT ON    --打開服務器輸出
SQL> EXEC P_EXE_LINUX('ls -l')

PL/SQL 過程已成功完成。  --此時沒有任何輸出,即使java 執行錯誤。

SQL> exec dbms_java.set_output(1111111111111);   --打開java 輸出

PL/SQL 過程已成功完成。
SQL> EXEC P_EXE_LINUX('ls -l')
EXECUTE IS ERROR!
the Permission ("java.io.FilePermission" "<<ALL FILES>>" "execute") has not been granted to WX. The
PL/SQL to grant this is dbms_java.grant_permission( 'WX', 'SYS:java.io.FilePermission', '<<ALL
FILES>>', 'execute' )

PL/SQL 過程已成功完成。

SQL>

 

出現以上錯誤解決辦法:

 

SQL> conn / as sysdba    --切換sys用戶
已連接。
SQL> exec dbms_java.grant_permission( 'WX', 'SYS:java.io.FilePermission', '<<ALL FILES>>', 'execute' )  

PL/SQL 過程已成功完成。

SQL> conn wx/123   --切換普通用戶
已連接。
SQL> EXEC P_EXE_LINUX('ls -l')   

PL/SQL 過程已成功完成。    --執行沒有輸出,切換用戶后,需要重新執行dbms_java.set_output和 set serveroutput on 

SQL> exec dbms_java.set_output(1111111111111);

PL/SQL 過程已成功完成。

SQL> EXEC P_EXE_LINUX('ls -l')

PL/SQL 過程已成功完成。

SQL> SET SERVEROUTPUT ON
SQL> EXEC P_EXE_LINUX('ls -l')  成功執行
total 48
-rwxrwx---+ 1 Administrators None           3584 Oct 22 17:59 PWDwx.ora
-rwxrwx---+ 1 Unknown+User   Unknown+Group  3584 Nov  1 16:39 SPFILEWX.ORA
drwxrwx---+ 1 Administrators None              0 Oct 19 09:58 archive
-rwxrwx---+ 1 Unknown+User   Unknown+Group  2048 Oct 19 12:23 hc_wx.dat
-rwxrwx---+ 1 Administrators None          31744 Dec 21  2005 oradba.exe
-rwxrwx---+ 1 Unknown+User   Unknown+Group  2647 Nov  1 16:27 oradim.log
total 48
-rwxrwx---+ 1 Administrators None           3584 Oct 22 17:59 PWDwx.ora
-rwxrwx---+ 1 Unknown+User   Unknown+Group  3584 Nov  1 16:39 SPFILEWX.ORA
drwxrwx---+ 1 Administrators None              0 Oct 19 09:58 archive
-rwxrwx---+ 1 Unknown+User   Unknown+Group  2048 Oct 19 12:23 hc_wx.dat
-rwxrwx---+ 1 Administrators None          31744 Dec 21  2005 oradba.exe
-rwxrwx---+ 1 Unknown+User   Unknown+Group  2647 Nov  1 16:27 oradim.log

PL/SQL 過程已成功完成。

SQL>

 

 執行導出,要確保用戶具有導出數據庫的權限,這里我的用戶授予了dba角色,演示如下:

  C:\Users\nantian>sqlplus / as sysdba

  SQL*Plus: Release 12.2.0.1.0 Production on 星期五 11月 2 08:37:46 2018

  Copyright (c) 1982, 2016, Oracle. All rights reserved.


  連接到:
  Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

  SQL> grant dba to wx;

  授權成功。

  SQL>

C:\Users\nantian>sqlplus wx/123

SQL*Plus: Release 12.2.0.1.0 Production on 星期四 11月 1 16:51:00 2018

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

上次成功登錄時間: 星期四 11月 01 2018 16:50:47 +08:00

連接到:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> set serveroutput on
SQL> exec dbms_java.set_output(1111111111111);

PL/SQL 過程已成功完成。

SQL> exec p_exe_linux('expdp zhjf/123 dumpfile=111111111.dmp logfile=1111111.log tables=SYS_PARAM')
Export: Release 12.2.0.1.0 - Production on 星期四 11月 1 16:51:37 2018
Copyright (c) 1982, 2017, Oracle and/or its affiliates.  All rights reserved.
連接到: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit
Production
啟動 "ZHJF"."SYS_EXPORT_TABLE_01":  zhjf/******** dumpfile=111111111.dmp
logfile=1111111.log tables=SYS_PARAM
處理對象類型 TABLE_EXPORT/TABLE/TABLE_DATA
處理對象類型 TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
處理對象類型 TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
處理對象類型 TABLE_EXPORT/TABLE/STATISTICS/MARKER
處理對象類型 TABLE_EXPORT/TABLE/TABLE
處理對象類型 TABLE_EXPORT/TABLE/INDEX/INDEX
處理對象類型 TABLE_EXPORT/TABLE/CONSTRAINT/CONSTRAINT
. . 導出了 "ZHJF"."SYS_PARAM"                              0 KB       0 行
已成功加載/卸載了主表 "ZHJF"."SYS_EXPORT_TABLE_01"
******************************************************************************
ZHJF.SYS_EXPORT_TABLE_01 的轉儲文件集為:
E:\APP\NANTIAN\VIRTUAL\ADMIN\WX\DPDUMP\111111111.DMP
作業 "ZHJF"."SYS_EXPORT_TABLE_01" 已於 星期四 11月 1 16:52:22 2018 elapsed 0
00:00:40 成功完成

PL/SQL 過程已成功完成。

SQL>

 

此處只演示了實現例子,如備份文件名重復會導致備份失敗,,可在java中將dmp文件名拼接為日期精確到時分秒,可解決備份文件存在錯誤。

 

 

自動生成文件名備份,傳入參數總無需寫入文件名

 創建javasource 名稱為Auto_Exp如下:

SQL> create or replace and compile java source named Auto_Exp as
  2  import java.io.BufferedReader;
  3  import java.io.InputStream;
  4  import java.io.InputStreamReader;
  5  import java.net.UnknownHostException;
  6  import java.text.DateFormat;
  7  import java.text.SimpleDateFormat;
  8  import java.util.Date;
  9  public class Auto_Exp
 10  {
 11
 12    public  static  String exe_cmd(String str,String schema){
 13    String exe_str="";
 14     Runtime runtime=Runtime.getRuntime();
 15      StringBuffer  enco  =  new  StringBuffer();
 16      enco.append("GBK");
 17         Date date = new Date();
 18         SimpleDateFormat df2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
 19  //UUID uuid=UUID.randomUUID();
 20        String dmpName=df2.format(date).replaceAll("\\s", "").replaceAll(":", "").replaceAll("-", "");
 21  System.out.println("FileName:"+schema+"_"+dmpName+".dmp");
 22      exe_str=str+" "+"dumpfile="+schema+"_"+dmpName+".dmp"+" "+"logfile="+schema+"_"+dmpName+".log";
 23      System.out.println("Exe_Message:"+exe_str);
 24   try{
 25
 26      Process proc =runtime.exec(exe_str);
 27      InputStream inp_suc=proc.getInputStream();
 28      InputStream inp_err=proc.getErrorStream();
 29      BufferedReader bfr_err = new BufferedReader(new InputStreamReader(inp_err,enco.toString()));
 30      BufferedReader bfr_suc = new BufferedReader(new InputStreamReader(inp_suc,enco.toString()));
 31       String strLine;
 32           while( (strLine=(bfr_suc.readLine())) != null){
 33
 34         System.out.println(strLine);
 35             }
 36      while( (strLine=(bfr_err.readLine())) != null){
 37
 38        System.out.println(strLine);
 39       }
 40           proc.destroy();
 41           inp_suc.close();
 42           inp_err.close();
 43       }catch (Exception e) {
 44          System.out.println("EXECUTE IS ERROR!");
 45          System.out.println(e.getMessage());
 46        }
 47        System.out.println("FINISHED !");
 48
 49
 50      return "";
 51    }
 52
 53  }
 54  /

Java 已創建。

 

創建過程

 

SQL> create or replace procedure auto_exp(str varchar2,str2 varchar2) as language java
  2  name 'Auto_Exp.exe_cmd(java.lang.String,java.lang.String)';
  3  /

過程已創建。

SQL>

 

開始執行測試

 exec Auto_Exp('expdp zhjf/1 ','zhjf')

 

傳入參數解釋:第一個參數導出完整命令,詳細命令格式參見expdp help=y 查看,第二個我參數為導出的用戶,文件名和日志名自動生成,規則可以在java代碼中修改,

 

linux和unix 中執行 exec Auto_Exp('expdp zhjf/1 ','zhjf') 可能報錯誤,請參見上述部署中鍵入 EXEC P_EXE_LINUX('env') 

這里我連接了一台Linux oralce 服務器,
 查看環境變量信息,如下:

C:\Users\nantian>sqlplus ecmapp/ecmapp@10.10.54.253:1521/ecmdb

SQL*Plus: Release 12.2.0.1.0 Production on 星期四 11月 1 17:32:33 2018

Copyright (c) 1982, 2016, Oracle. All rights reserved.

上次成功登錄時間: 星期五 11月 02 2018 00:30:23 +08:00

連接到:
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
With the Partitioning, OLAP, Advanced Analytics and Real Application Testing options

SQL> set serveroutput on
SQL> exec dbms_java.set_output(111111111);

PL/SQL 過程已成功完成。

SQL> EXEC P_EXE_LINUX('env')
LESSKEY=/etc/lesskey.bin
XDG_VTNR=1
NNTPSERVER=news
MANPATH=/usr/local/man:/usr/share/man
XDG_SESSION_ID=1
HOSTNAME=ecmos
XKEYSYMDB=/usr/X11R6/lib/X11/XKeysymDB
HOST=ecmos
SHELL=/bin/bash
TERM=linux
PROFILEREAD=true
HISTSIZE=1000
MORE=-sl
USER=oracle
LD_LIBRARY_PATH=/oracle/product/12.1.0/lib:
LS_COLORS=no=00:fi=00:di=01;34:ln=00;36:pi=40;33:so=01;35:do=01;35:bd=40;33;01:c
d=40;33;01:or=41;33;01:ex=00;32:*.cmd=00;32:*.exe=01;32:*.com=01;32:*.bat=01;32:
*.btm=01;32:*.dll=01;32:*.tar=00;31:*.tbz=00;31:*.tgz=00;31:*.rpm=00;31:*.deb=00
;31:*.arj=00;31:*.taz=00;31:*.lzh=00;31:*.lzma=00;31:*.zip=00;31:*.zoo=00;31:*.z
=00;31:*.Z=00;31:*.gz=00;31:*.bz2=00;31:*.tb2=00;31:*.tz2=00;31:*.tbz2=00;31:*.x
z=00;31:*.avi=01;35:*.bmp=01;35:*.fli=01;35:*.gif=01;35:*.jpg=01;35:*.jpeg=01;35
:*.mng=01;35:*.mov=01;35:*.mpg=01;35:*.pcx=01;35:*.pbm=01;35:*.pgm=01;35:*.png=0
1;35:*.ppm=01;35:*.tga=01;35:*.tif=01;35:*.xbm=01;35:*.xpm=01;35:*.dl=01;35:*.gl
=01;35:*.wmv=01;35:*.aiff=00;32:*.au=00;32:*.mid=00;32:*.mp3=00;32:*.ogg=00;32:*
.voc=00;32:*.wav=00;32:
ORACLE_SID=ecmdb
XNLSPATH=/usr/share/X11/nls
ORACLE_BASE=/oracle
QEMU_AUDIO_DRV=pa
HOSTTYPE=x86_64
FROM_HEADER=
PAGER=less
CSHEDIT=emacs
XDG_CONFIG_DIRS=/etc/xdg
MINICOM=-c on
MAIL=/var/spool/mail/oracle
PATH=
CPU=x86_64
INPUTRC=/etc/inputrc
PWD=/oracle
LANG=en_US.UTF-8
PYTHONSTARTUP=/etc/pythonstart
GPG_TTY=/dev/tty1
AUDIODRIVER=pulseaudio
QT_SYSTEM_DIR=/usr/share/desktop-data
SHLVL=1
XDG_SEAT=seat0
HOME=/oracle
ALSA_CONFIG_PATH=/etc/alsa-pulse.conf
SDL_AUDIODRIVER=pulse
LESS_ADVANCED_PREPROCESSOR=no
OSTYPE=linux
LS_OPTIONS=-N --color=tty -T 0
XCURSOR_THEME=DMZ
WINDOWMANAGER=env GNOME_SHELL_SESSION_MODE=sle-classic gnome-session --session
sle-classic
G_FILENAME_ENCODING=@locale,UTF-8,ISO-8859-15,CP1252
LESS=-M -I -R
MACHTYPE=x86_64-suse-linux
LOGNAME=oracle
CVS_RSH=ssh
XDG_DATA_DIRS=/usr/share
LESSOPEN=lessopen.sh %s
XDG_RUNTIME_DIR=/run/user/1001
ORACLE_HOME=/oracle/product/12.1.0
LESSCLOSE=lessclose.sh %s %s
G_BROKEN_FILENAMES=1
COLORTERM=1
_=/oracle/product/12.1.0/bin/sqlplus
ORA_NET2_DESC=17,20
ORACLE_SPAWNED_PROCESS=1

PL/SQL 過程已成功完成。

SQL>

 


請嘗試鍵入絕對路徑查看ORACLE_HOME變量,使用絕對路徑執行解決錯誤,如下:


exec Auto_Exp('/oracle/product/12.1.0/bin/expdp zhjf/1 ','zhjf')

 

windown 導出文件名日志名自動成示例:

C:\Users\nantian>sqlplus wx/123

SQL*Plus: Release 12.2.0.1.0 Production on 星期四 11月 1 17:39:34 2018

Copyright (c) 1982, 2016, Oracle.  All rights reserved.

上次成功登錄時間: 星期四 11月 01 2018 17:36:23 +08:00

連接到:
Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit Production

SQL> set serveroutput on
SQL> exec dbms_java.set_output(11111111111);

PL/SQL 過程已成功完成。

SQL>   exec Auto_Exp('expdp zhjf/123  tables=SYS_LOGGER','zhjf')
FileName:zhjf_20181101174028.dmp
Exe_Message:expdp zhjf/123  tables=SYS_LOGGER dumpfile=zhjf_20181101174028.dmp
logfile=zhjf_20181101174028.log
Export: Release 12.2.0.1.0 - Production on 星期四 11月 1 17:40:29 2018
Copyright (c) 1982, 2017, Oracle and/or its affiliates.  All rights reserved.
連接到: Oracle Database 12c Enterprise Edition Release 12.2.0.1.0 - 64bit
Production
啟動 "ZHJF"."SYS_EXPORT_TABLE_01":  zhjf/******** tables=SYS_LOGGER
dumpfile=zhjf_20181101174028.dmp logfile=zhjf_20181101174028.log
處理對象類型 TABLE_EXPORT/TABLE/TABLE_DATA
處理對象類型 TABLE_EXPORT/TABLE/INDEX/STATISTICS/INDEX_STATISTICS
處理對象類型 TABLE_EXPORT/TABLE/STATISTICS/TABLE_STATISTICS
處理對象類型 TABLE_EXPORT/TABLE/STATISTICS/MARKER
處理對象類型 TABLE_EXPORT/TABLE/TABLE
. . 導出了 "ZHJF"."SYS_LOGGER"                         735.9 MB 5455743 行
已成功加載/卸載了主表 "ZHJF"."SYS_EXPORT_TABLE_01"
******************************************************************************
ZHJF.SYS_EXPORT_TABLE_01 的轉儲文件集為:
E:\APP\NANTIAN\VIRTUAL\ADMIN\WX\DPDUMP\ZHJF_20181101174028.DMP
作業 "ZHJF"."SYS_EXPORT_TABLE_01" 已於 星期四 11月 1 17:41:28 2018 elapsed 0
00:00:57 成功完成
FINISHED !

PL/SQL 過程已成功完成。

SQL>

 

如上文件名為自動生成,且不易重復。

linux 示例命令有所不同需要將命令修改為絕對路徑的expdp 執行 exec Auto_Exp('/u01/app/oracle/product/11.2.0/db_1/bin/expdp zhjf/1 ','zhjf')

ORACLE_HOME為/u01/app/oracle/product/11.2.0/db_1

 

問題1:需要自動備份,可在Oracle中建一個定時任務,每天執行即可,也可將其做成函數,使用select 查詢及進行備份,

問題2:web頁面無法獲取日志問題,可將生成的日志文件作為oracle外部表,使用select 查詢及進行日志讀取。

附件下載地址:https://files.cnblogs.com/files/wenxiao1-2-3-4/plsql%E6%B5%8B%E8%AF%95.zip

參考鏈接:

數據庫包api :DBMS_DATAPUMP   https://docs.oracle.com/cd/B19306_01/server.102/b14215/dp_api.htm

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM