因客戶需求,需要在業務系統中,菜單中的網頁中的按鈕中加入一個按鈕,用於點擊備份數據庫
(環境:只配置了數據源連接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