zoukankan      html  css  js  c++  java
  • 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 antian>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
    antian>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:APPNANTIANVIRTUALADMINWXDPDUMP111111111.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 antian>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
    antian>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:APPNANTIANVIRTUALADMINWXDPDUMPHJF_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

  • 相关阅读:
    ServletConfig类
    坑爹的去哪儿网订酒店经历
    python + opencv + pycharm +语音生成
    最近看到的工作要求
    pip in windows
    路由器外接硬盘做nas可行吗?
    阅读201706
    scrum学习
    学习concurrency programming进展
    Reactor/Proactor的比较 (ZZ)
  • 原文地址:https://www.cnblogs.com/wenxiao1-2-3-4/p/9889621.html
Copyright © 2011-2022 走看看