SlideShare une entreprise Scribd logo
1  sur  70
Télécharger pour lire hors ligne
《CSDN 社区电子杂志——Oracle 杂志》




http://emag.csdn.net   -1-        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


                                                                        目录
目录 ........................................................................................................................................................- 2 -
数据库实战 ..........................................................................................................................................- 4 -
利用errorstack event解决问题 .............................................................................................................- 4 -

数据库开发 ..........................................................................................................................................- 8 -
Oracle外部例程......................................................................................................................................- 8 -

       1.1.       必要性 .................................................................................................................................- 8 -

       1.2.       基本原理 .............................................................................................................................- 9 -

       1.3.       使用配置 .............................................................................................................................- 9 -

       1.4.       使用COM对象说明 .......................................................................................................... - 11 -

       1.5.       操作Excel示例 ..................................................................................................................- 13 -

       1.6.       小结 ...................................................................................................................................- 21 -

数据库复制 ........................................................................................................................................- 23 -
最简单的创建只读实体化视图站点的方法 .......................................................................................- 23 -

       1.1.       主站点上创建实体化视图日志表....................................................................................- 23 -

       1.2.       实体化视图站点上创建公用数据库链接........................................................................- 23 -

       1.3.       实体化视图站点上创建刷新组,本例中 3 分钟刷新一次............................................- 23 -

       1.4.       实体化视图站点上创建用户私有数据库链接................................................................- 24 -

       1.5.       实体化视图站点上创建实体化视图................................................................................- 24 -

       1.6.       实体化视图站点上将创建的视图加入刷新组................................................................- 24 -

       1.7.       测试 ...................................................................................................................................- 24 -

       1.8.       总结 ...................................................................................................................................- 24 -

       1.9.       附录 ...................................................................................................................................- 25 -

Oracle高级复制冲突解决机制的研究................................................................................................- 27 -

数据库高可用性 ...............................................................................................................................- 37 -
SharePlex for Oracle ...........................................................................................................................- 37 -

       1.1.       前言 ...................................................................................................................................- 37 -

       1.2.       高可用容灾方案设计 .......................................................................................................- 37 -


http://emag.csdn.net                                                         -2-                                    2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

       1.3.      SharePlex for Oracle介绍..................................................................................................- 42 -

       1.4.      容灾系统建立 ...................................................................................................................- 47 -

       1.5.      关于Quest Software...........................................................................................................- 53 -

       1.6.      SharePlex for Oracle部分成功案例 ..................................................................................- 53 -

博文精品图书连载...........................................................................................................................- 55 -
《Oracle JDeveloper 10g 与 J2EE实践演练》 ...............................................................................- 55 -

       1.1.      J2EE 应用程序模型简介 .................................................................................................- 55 -

       1.2.      Oracle 应用程序开发框架(ADF) ...............................................................................- 56 -

       1.3.      Oracle JDeveloper 10g 功能概览.....................................................................................- 58 -

       1.4.      结语 ...................................................................................................................................- 67 -

       1.5.      本书相关资源 ...................................................................................................................- 67 -

关于CSDN..........................................................................................................................................- 69 -




http://emag.csdn.net                                                       -3-                                   2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


数据库实战

                利用 errorstack event 解决问题


                                                  本文作者: Kamus (kamusis@gmail.com )



    摘要:在任何一种解决问题之前,必须要先知道问题的原因,才可以作到有的放矢。解决问

题的方法并不是很难找,难能可贵的是能够及时准确地定位问题。本文介绍一种利用 trace event

来定位问题所在的方法。



某天现场人员报告说 exp 的时候报权限不足的错误。

是用当前用户作的用户级别的 exp,按理说应该没有什么权限的问题。

按照现场的情况作了测试,果然重现了问题。


    d:Temp>exp parfile=exp.par


    Export: Release 9.2.0.5.0 - Production on Tue Dec 21 22:27:13 2004


    Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.




    EXP-00008: ORACLE error 1031 encountered
    ORA-01031: insufficient privileges
    EXP-00000: Export terminated unsuccessfully



其中 exp.par 的内容如下:
    userid=scott/tiger
    file=.scott.dmp
    indexes=y
    grants=y
    rows=y
    constraints=y
    owner=scott
    direct=n

http://emag.csdn.net                     -4-                2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
    compress=n
    feedback=10000
    resumable=y
    resumable_timeout=7200
    log=.export.log



没有发现什么问题,那么作一个 trace 吧,于是决定使用 errorstack event,由于 exp 是在命令行中

直接执行的,所以只能对整个数据库系统作 trace,由于只是想知道 ORA-01031 错误的发生原因,

所以用以下语句:
    alter system set events '1031 trace name errorstack level 3';




   如果想捕获什么错误,就直接用错误号作 trace,此处我们想获知 ORA-01031 的错误原因,
   所以使用了’1031 trace name errorstack level 3’。



然后重新运行 exp,仍然报错,这时候在 udump 目录中生成了 trace 文件,检查文件内容,发现:
    *** SESSION ID:(15.210) 2004-12-21 22:22:36.704
    *** 2004-12-21 22:22:36.704
    ksedmp: internal or fatal error
    ORA-01031: insufficient privileges
    Current SQL statement for this session:
    ALTER SESSION ENABLE RESUMABLE TIMEOUT 7200



原来问题出在 ENABLE RESUMABLE 部分,这是 9i 的新特性,用于在出现空间不足的问题时,

挂起整个操作以等待操作人员解决空间问题。



只要确认了问题所在,就很好解决了,其实如果详细地看过 adminitrator 文档,也就不会犯这个错

误,文档里面 Enabling and Disabling Resumable Space Allocation 部分很清楚地写着:如果要使用

resumbale 特性,那么必须有 resumable 系统权限。



检查现场用户的权限,发现只有 connect 和 resource 权限。于是:
    grant resumable to username;



当然如果象一些应用里面那样,用户始终是具有 DBA 角色的话,那么永远也不会发生这个错误,

因为 DBA 角色本来就具有 esumable 系统权限。不过为了安全起见,我们的应用中用户都不会具有
http://emag.csdn.net                     -5-               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

DBA 权限。




   解决问题的方法很简单,没什么好说的,本文想介绍的也是发现问题的手段,也就是利用
   set events 的方法。这个方法在我们对一个错误感到莫名其妙的时候往往会成为指路明
   灯。



作为本文的补充,提供几个常见的用于 Troubleshooting 或者 Tuning 或者 Interal 研究的 Oracle

Events。



10032 事件:用于 dump 排序操作的统计值,Level 10 是最详细的级别。
    ALTER SESSION SET EVENTS '10032 trace name context forever, level 10';



10046 事件:用于跟踪 SQL 执行过程,这是我们在调整一个 SQL 时比较常见的方法。Level 12

是最详细的级别。
    ALTER SESSION SET EVENTS '10046 trace name context forever, level 12';

其中各个 Level 的含义:

1:显示 SQL 语句,执行计划和执行统计值

4:显示级别 1 的内容和绑定变量

8:显示级别 1 的那同和等待事件统计

12:显示级别 1 的内容和绑定变量、等待事件统计



10053 事件:当 Oracle 使用 CBO 进行执行计划的生成时,可以使用这个事件对于执行计划的生

成过程进行跟踪。
    ALTER SESSION SET EVENTS '10053 trace name context forever, level 1';



10081 事件:用于跟踪 HWM(高水位标志)的变更
    ALTER SESSION SET EVENTS '10081 trace name context forever, level 1';




http://emag.csdn.net                   -6-                 2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

作者简介:
                 张乐奕,网名 kamus



                 曾任 ITPUB Oracle 认证版版主,现任 itpub Oracle 管理版版主。




现任职于北京某大型软件公司,首席DBA,主要负责证券行业的全国十数处核心交易系统数据库管

理及维护工作。

热切关注Oracle技术和其它相关技术,出没于各大数据库技术论坛,目前是中国最大的Oracle技

术论坛www.itpub.net的数据库管理版版主。

    阅读更多技术文章和随笔可以登录我的个人blog。

    http://blog.dbform.com。




http://emag.csdn.net              -7-            2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


数据库开发

                       Oracle 外部例程

                                         —— PL/SQL 操作 COM 对象


                                          本文作者: chanet (chanet@oracle.com.cn )



    PL/SQL 是由 Oracle 公司对标准 SQL 进行扩展,专用于 Oracle 数据库中程序设计的专用语言,

属第三代过程式程序设计语言。从 Oracle8 开始提供了直接从 PL/SQL 中调用外部 C 语言过程,允

许开发人员用 PL/SQL 进行使用 C 语言编制的程序模块。从 Oracle8i 开始,又引入了 Java 程序。

在本文中主要介绍外部例程的基本原理以及使用条件,介绍如何通过引用外部例程来操作

Windows 中的 COM 对象,并做了一个操作 Excel 对象的示例。

    本 文 的 运 行 环 境 全 部 建 立 在 Oracle9i 和 Windows2000 。 其 中 ORACLE 的 安 装 目 录

(ORACLE_HOME)为 D:oracleora92,SID 为 ORADB,主机名为 CHANET。



1.1. 必要性

    扩展后的 PL/SQL 语言已经集成了标准 SQL,在效率和安全上非常适合设计 Oracle 数据库程

序,但对于应用的某些功能,其它的程序设计语言比 PL/SQL 更适合,如:使用操作系统资源,C

语言在计算和引用系统对象及使用设备上优于 PL/SQL, Java 语言在网络上的应用优于 PL/SQL。
                            而

如果在应用上要用到不适合用 PL/SQL 语言的话,这时就要使用其它语言进行编制,然后由 PL/SQL

作为外部例程进行调用。

    在 Oracle8 之 前 的 版 本 , PL/SQL 和 其 它 语 言 的 唯 一 通 信 是 借 助 于 DBMS_PIPE 和

DBMS_ALERT 包来实现,在使用之前必需建立一个 OCI 接口或预编译器编制的监护程序,使用

比较复杂。外部例程的出现,只需在 PL/SQL 中建立一个函数映射到外部例程对应的函数,就像普

通的 PL/SQL 函数使用一样,简化了使用过程。




http://emag.csdn.net               -8-                2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.2. 基本原理

    当引用外部 C 语言例程时,Oracle 监听器将启动 extproc 进程,该进程将会动态地载入共享库

(在 Windows 下称为动态链接库,即是 DLL 文件),进程起了一个缓冲的作用,当 PL/SQL 过程

调用外部函数时,进程把命令发送到共享库,之后把结果返回给 PL/SQL 过程。

进程被调用后随着共享库的使用会话(session)而存在,如果调用完毕或者关闭数据库用户会话,

extproc 进程会自动关闭。

    如下图 1-1 为调用外部例程的描述。




                                   图 1-1 监听器与 extproc 进程




1.3. 使用配置

    在调用外部例程之前,必需进行如下设置:
        配置监听器。
        配置 Net 组件服务。
    配置监听器,打开 D:oracleora92networkadminlistener.ora 文件,修改文件参数。
      LISTENER =
        (DESCRIPTION_LIST =
          (DESCRIPTION =
            (ADDRESS_LIST =
                (ADDRESS = (PROTOCOL = TCP)(HOST = CHANET)(PORT = 1521))
            )
            (ADDRESS_LIST =

http://emag.csdn.net                          -9-                    2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                     (ADDRESS = (PROTOCOL = IPC)(KEY = extproc1))
                 )
            )
        )


      SID_LIST_LISTENER =
        (SID_LIST =
            (SID_DESC =
                 (SID_NAME = PLSExtProc)
                 (ORACLE_HOME = D:oracleora92)
                 (PROGRAM = extproc)
            )
            (SID_DESC =
                (GLOBAL_DBNAME = ORADB)
                (ORACLE_HOME = D:oracleora92)
                (SID_NAME = ORADB)
            )
        )

其中有两部份参数对于使用外部例程是很重要的。
    (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = extproc1))

    设置基于 IPC 协议的外部例程
    (SID_DESC =(SID_NAME = PLSExtProc) (ORACLE_HOME = D:oracleora92) (PROGRAM = extproc) )

    记录数据库的相关属性,SID_NAME 在默认的情况下是 PLSExtproc。

    配置 Net 组件服务,打开 D:oracleora92networkadmintnsnames.ora 文件,把如下内容保存在

该文件里。
      EXTPROC_CONNECTION_DATA =
        (DESCRIPTION =
            (ADDRESS_LIST =
                 (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
            )
            (CONNECT_DATA =
                 (SID = PLSExtProc)
                 (PRESENTATION = RO)
            )
        )

    重要参数说明:
    (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1))
    (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO)

    两设置必需与 listener.ora 里的一致。

    重启监听器,并测试服务是否可用。

http://emag.csdn.net                               - 10 -                2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

    停止监听器:lsnrctl stop

    启动监听器:lsnrctl start

    测试服务是否可用:

      C:>tnsping EXTPROC_CONNECTION_DATA

      TNS Ping Utility for 32-bit Windows: Version 9.2.0.1.0 - Production on 07-4 月 -2

      005 16:57:00

      Copyright (c) 1997 Oracle Corporation.     All rights reserved.

      已使用的参数文件:

      D:oracleora92networkadminsqlnet.ora

      已使用 TNSNAMES 适配器来解析别名

      Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)

      (KEY = EXTPROC1))) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO)))

      OK(30 毫秒)

    测试 extproc 进程是否正常:

      D:oracleora92bin>extproc

      Oracle Corporation --- 星期四 4 月 07 2005 17:37:18.968

      Heterogeneous Agent Release 9.2.0.1.0 - Production




1.4. 使用 COM 对象说明

    COM 对象设计都会提供了三个基本操作给开发人员使用,分别为:获取属性值,设置属性值

(只读属性除外),调用方法。Oracle 数据库在 Windows 的平台下提供了操作 COM 对象的接口,

属于 C 语言外部例程模式。

    工作原理如下图:




http://emag.csdn.net                                     - 11 -                    2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》




                                       图 1-2 操作 COM 对象工作原理

    在使用该功能之前,需明白如下内容:

    1、创建 COM 对象操作函数。
      SQL> CONNECT SYSTEM/chanet@oradb
      SQL> CREATE USER chanet identified by chanet;
      SQL> GRANT CREATE LIBRARY TO chanet;
      SQL> CONNECT chanet/chanet@oradb;
      SQL> @D:oracleora92comcomwrap.sql;

    2、配置监听器。

    在 listener.ora 文件里,添加如下内容,并重启监听器。
      STARTUP_WAIT_TIME_LISTENER = 0
      CONNECT_TIMEOUT_LISTENER = 10
      TRACE_LEVEL_LISTENER = off
      PASSWORDS_LINTENER = (oracle)

    3、PL/SQL 数据类型与对应的 COM 对象类型。

                                       表 1-1 数据类型比较

    PL/SQL 数据类型                            COM API 数据类型
    VARCHAR2                               BSTR
    BOOLEAN                                BOOL
    BINARY_INTEGER                         BYTE,INT,LONG
    DOUBLE PRECISION                       DOUBLE,FLOAT,CURRENCY
    DATE                                   DATE
    4、函数说明。

                                        表 1-2 函数说明

         名称                                         功能描述
    CreateObject       创建对象
    DestroyObject      关闭对象
    GetLastError       获取错误信息
http://emag.csdn.net                       - 12 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
    GetProperty        获取属性值
    SetProperty        设置属性值
    InitArg            为 Invoke 函数初始化参数
    InitOutArg         为 GetArg 初始化输出参数
    GetArg             获取输出参数
    SetArg             为 Invoke 函数设置参数
    Invoke             调用 COM 对象的函数或过程




1.5. 操作 Excel 示例

    本节介绍如何操作 COM 对象(以 Excel 对象为例) 将数据库里的表记录通过 PL/SQL 语句输
                                ,

出成 Excel 文件。通过对象浏览器可以查看 Excel 对象提供的属性和方法。
                                        (如:在 Excel 菜单,工

具 -> 宏 -> 打开 Visual Basic 编辑器,在编辑器里,视图 -> 对象浏览器)。

    使用 Excel 对象一般针对单元格进行操作(如,设置第一个单元格字体大小的代码为:

Range("A1").Font.Size = 20)。对应的 COM 外部例程操作的步骤为:1、获取程序句柄;2、获取工

作簿句柄;3、获取工作表句柄;4、获取 Range 区句柄;5、获取 Font 类句柄;6、设置 Size 属性。

    如下为操作 Excel 对象的例子,首先建立示例表,然后建立操作包(package),最后是使用包

函数的过程(procedure)
               。创建一个测试用表:



      -- 销售表(脚本)
      CREATE TABLE IT_SALE_TAB(ITS_ID VARCHAR2(5),ITS_DATE DATE,ITS_TOTAL NUMBER);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('1',TO_DATE('2004-01-01','YYYY-MM-DD'),250);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('2',TO_DATE('2004-02-01','YYYY-MM-DD'),150);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('3',TO_DATE('2004-03-01','YYYY-MM-DD'),80);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('4',TO_DATE('2004-04-01','YYYY-MM-DD'),96);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('5',TO_DATE('2004-05-01','YYYY-MM-DD'),300);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('6',TO_DATE('2004-06-01','YYYY-MM-DD'),210);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('7',TO_DATE('2004-07-01','YYYY-MM-DD'),320);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('8',TO_DATE('2004-08-01','YYYY-MM-DD'),280);


http://emag.csdn.net                       - 13 -                 2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('9',TO_DATE('2004-09-01','YYYY-MM-DD'),276);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('10',TO_DATE('2004-10-01','YYYY-MM-DD'),368);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('11',TO_DATE('2004-11-01','YYYY-MM-DD'),163);
      INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL)
         VALUES('12',TO_DATE('2004-12-01','YYYY-MM-DD'),305);
      COMMIT;




    操作 Excel 对象包(Package)。


      CREATE OR REPLACE PACKAGE oraExcel IS
          xlThin                  BINARY_INTEGER DEFAULT 2;
          DummyToken              BINARY_INTEGER;

          applicationToken        BINARY_INTEGER:=-1;    -- Excel 对象句柄
          WorkBooksToken          BINARY_INTEGER:=-1;    -- 工作簿句柄
          WorkBookToken           BINARY_INTEGER:=-1;

          WorkSheetToken          BINARY_INTEGER:=-1;    -- 工作表句柄
          WorkSheetToken1         BINARY_INTEGER:=-1;

          RangeToken              BINARY_INTEGER:=-1;    -- Range 区句柄
          ChartObjectToken        BINARY_INTEGER:=-1;    -- 图表对象句柄
          ChartObject1            BINARY_INTEGER:=-1;
          Chart1Token             BINARY_INTEGER:=-1;
          hLines                  BINARY_INTEGER:=-1;
          i                       BINARY_INTEGER;
          err_src                 VARCHAR2(255);
          err_desc                VARCHAR2(255);
          err_hpf                 VARCHAR2(255);
          err_hpID                BINARY_INTEGER;

         -- 创建 Excel 对象
         FUNCTION CreateExcelWorkSheet(servername VARCHAR2) RETURN BINARY_INTEGER;

         -- 插入数据(字符型)
         FUNCTION setCellValues(RANGE VARCHAR2,data VARCHAR2,TYPE VARCHAR2)
              RETURN BINARY_INTEGER;

         -- 插入数据(日期型)
         FUNCTION setCellValues(RANGE VARCHAR2,data DATE,TYPE VARCHAR2)
              RETURN BINARY_INTEGER;

         -- 插入数据(整型)
         FUNCTION setCellValues(RANGE VARCHAR2,data BINARY_INTEGER,TYPE VARCHAR2)
              RETURN BINARY_INTEGER;

         -- 插入数据(实型)
         FUNCTION setCellValuesReal(RANGE VARCHAR2,data DOUBLE PRECISION,TYPE VARCHAR2)

http://emag.csdn.net                          - 14 -                2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
            RETURN BINARY_INTEGER;

         -- 设置列宽
         FUNCTION setCellColWidth(RANGE VARCHAR2,width DOUBLE PRECISION,TYPE VARCHAR2) RETURN
      BINARY_INTEGER;

         -- 设置表格
         FUNCTION        setCellLines(RANGE     VARCHAR2,BordersIndex      BINARY_INTEGER,weight
      BINARY_INTEGER DEFAULT xlThin,TYPE VARCHAR2) RETURN BINARY_INTEGER;

         -- 合并单元格
         FUNCTION setCellMerge(RANGE VARCHAR2,bValues BOOLEAN,TYPE VARCHAR2)
            RETURN BINARY_INTEGER;

         -- 设置字体属性
         FUNCTION setCellFont(RANGE VARCHAR2,Property VARCHAR2,
            fontValues BINARY_INTEGER,TYPE VARCHAR2) RETURN BINARY_INTEGER;

         -- 调用方法
         FUNCTION callMethod(RANGE VARCHAR2,MethodName VARCHAR2) RETURN BINARY_INTEGER;

         -- 插入图表
         FUNCTION InsertChart(xpos BINARY_INTEGER,ypos BINARY_INTEGER,
                             width BINARY_INTEGER,height BINARY_INTEGER,
                             RANGE VARCHAR2,TYPE VARCHAR2) RETURN BINARY_INTEGER;

         -- 保存文件
         FUNCTION SaveToFile(filename VARCHAR2) RETURN BINARY_INTEGER;

         -- 关闭 Excel 对象
         FUNCTION CloseExcel RETURN BINARY_INTEGER;
      END oraExcel;




    数据包体内容(PACKAGE BODY)


      CREATE OR REPLACE PACKAGE BODY oraExcel IS
         FUNCTION CreateExcelWorkSheet(servername VARCHAR2) RETURN BINARY_INTEGER IS
         BEGIN

             -- 创建 Excel 对象
             i:=ordcom.CreateObject('Excel.Application', 0, servername,applicationToken);

             IF (i!=0) THEN    -- 创建失败,提示返回的错误信息
                  ordcom.GetLastError(err_src, err_desc, err_hpf, err_hpID);
                  raise_application_error(-20000,err_src || err_desc || err_hpf || err_hpID);
             END IF;

             -- 通过程序对象句柄获取工作簿句柄
              i:=ordcom.GetProperty(applicationToken, 'WorkBooks', 0, WorkBooksToken);
                 ordcom.InitArg();
                 ordcom.SetArg(-4167,'I4');
                 i:=ordcom.Invoke(WorkBooksToken, 'Add', 1, WorkBookToken);
                 ordcom.InitArg();
                 ordcom.SetArg('Sheet 1','BSTR');

http://emag.csdn.net                          - 15 -                    2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
              -- 获取工作表句柄
              i:=ordcom.GetProperty(applicationToken, 'WorkSheets', 0, WorkSheetToken1);
              i:=ordcom.Invoke(WorkSheetToken1, 'Add', 0, WorkSheetToken);
              RETURN i;
         END CreateExcelWorkSheet;
         FUNCTION setCellValues(RANGE VARCHAR2,data VARCHAR2, TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE,'BSTR');

                 -- 获取 Range 区句柄,之后将数据写入到指定的单元格
                 i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken);
                 i:=ordcom.SetProperty(RangeToken, 'Value', data, TYPE);
                 i:=ordcom.DestroyObject(RangeToken);
                 RETURN i;
         END setCellValues;
         FUNCTION setCellValues(RANGE VARCHAR2,data BINARY_INTEGER,TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE, 'BSTR');
                 i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken);
                 i:=ordcom.SetProperty(RangeToken, 'Value', data, type);
                 i:=ordcom.DestroyObject(RangeToken);
                 RETURN i;
         END setCellValues;
         FUNCTION setCellValuesReal(RANGE VARCHAR2,data DOUBLE PRECISION,TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE, 'BSTR');
                 i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken);
                 i:=ordcom.SetProperty(RangeToken, 'Value', data, type);
                 i:=ordcom.DestroyObject(RangeToken);
                 RETURN i;
         END setCellValuesReal;
         FUNCTION setCellValues(RANGE VARCHAR2,data DATE,TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE, 'BSTR');
                 i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken);
                 i:=ordcom.SetProperty(RangeToken, 'Value', data, TYPE);
                 i:=ordcom.DestroyObject(RangeToken);


http://emag.csdn.net                            - 16 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                 RETURN i;
         END setCellValues;
         FUNCTION setCellColWidth(RANGE VARCHAR2,width DOUBLE PRECISION,TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE,'BSTR');
                 i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken);
                 i:=ordcom.SetProperty(RangeToken,'ColumnWidth',width,TYPE);
                 i:=ordcom.DestroyObject(RangeToken);
                 RETURN i;
         END setCellColWidth;
         FUNCTION setCellMerge(RANGE VARCHAR2,bValues BOOLEAN,TYPE VARCHAR2)
            RETURN BINARY_INTEGER IS
         BEGIN
                 ordcom.InitArg();
                 ordcom.SetArg(RANGE,'BSTR');
                 i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken);
                 i:=ordcom.SetProperty(RangeToken,'MergeCells',bValues,'BOOLEAN');
                 i:=ordcom.DestroyObject(RangeToken);
                 RETURN i;
         END setCellMerge;
         FUNCTION setCellLines(RANGE VARCHAR2,BordersIndex BINARY_INTEGER,
            weight BINARY_INTEGER DEFAULT xlThin,TYPE VARCHAR2) RETURN BINARY_INTEGER IS
         BEGIN
             ordcom.InitArg();
             ordcom.SetArg(RANGE,'BSTR');
             i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken);
             ordcom.InitArg();

             ordcom.SetArg(BordersIndex,TYPE); -- 画表格的具体载入参数
             i:=ordcom.GetProperty(RangeToken,'Borders',1,hLines);
             i:=ordcom.SetProperty(hLines,'weight',weight,TYPE);
             i:=ordcom.DestroyObject(hLines);
             i:=ordcom.DestroyObject(RangeToken);
             RETURN i;
         END setCellLines;
         FUNCTION setCellFont(RANGE VARCHAR2,Property VARCHAR2,fontValues BINARY_INTEGER,TYPE
      VARCHAR2) RETURN BINARY_INTEGER IS
         BEGIN
             ordcom.InitArg();
             ordcom.SetArg(RANGE,'BSTR');
             i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken);
             ordcom.InitArg();
             ordcom.SetArg(Property,TYPE);


http://emag.csdn.net                            - 17 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                i:=ordcom.GetProperty(RangeToken,'Font',0,hLines); -- 获取字体对象
                i:=ordcom.SetProperty(hLines,Property,fontValues,TYPE);
                i:=ordcom.DestroyObject(hLines);
                i:=ordcom.DestroyObject(RangeToken);
                RETURN i;
         END;
         FUNCTION callMethod(RANGE VARCHAR2,MethodName VARCHAR2) RETURN BINARY_INTEGER IS
           reti BINARY_INTEGER := -1;
         BEGIN
                ordcom.InitArg();
                ordcom.SetArg(RANGE,'BSTR');
                i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken);
                ordcom.InitArg();

                i:=ordcom.Invoke(RangeToken,MethodName,0,reti);   -- 调用对象的方法
                i:=ordcom.DestroyObject(RangeToken);
                RETURN reti;
         END;
         FUNCTION InsertChart(xpos BINARY_INTEGER, ypos BINARY_INTEGER,
                                width BINARY_INTEGER, height BINARY_INTEGER,
                                RANGE VARCHAR2, TYPE VARCHAR2)
           RETURN BINARY_INTEGER IS
                     charttype BINARY_INTEGER:= -4099;
         BEGIN
                  ordcom.InitArg();
                  i:=ordcom.GetProperty(WorkSheetToken, 'ChartObjects', 0, ChartObjectToken);
                  ordcom.InitArg();

                  ordcom.SetArg(xpos,'I2'); -- 载入图表对象位置参数
                  ordcom.SetArg(ypos,'I2');
                  ordcom.SetArg(width,'I2');
                  ordcom.SetArg(height,'I2');

                  i:=ordcom.Invoke(ChartObjectToken, 'Add', 4, ChartObject1); -- 添加图表
                  i:=ordcom.GetProperty(ChartObject1, 'Chart', 0,Chart1Token);
                  ordcom.InitArg();
                  ordcom.SetArg(RANGE, 'BSTR');

                  i:=ordcom.GetProperty(WorkSheetToken,'Range', 1, RangeToken); -- 选取区域
                  ordcom.InitArg();
                  ordcom.SetArg(RangeToken, 'DISPATCH');
                  IF TYPE='xlPie' THEN
                       charttype := -4102;
                  ELSIF TYPE='xl3DBar' THEN
                       charttype := -4099;
                  ELSIF TYPE='xlBar' THEN
                       charttype := 2;
                  ELSIF TYPE='xl3dLine' THEN


http://emag.csdn.net                            - 18 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                       charttype:= -4101;
                 END IF;
                 ordcom.SetArg(charttype,'I4');
                 i:=ordcom.Invoke(Chart1Token,'ChartWizard', 2, DummyToken);
                 i:=ordcom.DestroyObject(RangeToken);
                 i:=ordcom.DestroyObject(ChartObjectToken);
                 i:=ordcom.DestroyObject(ChartObject1);
                 i:=ordcom.DestroyObject(Chart1Token);
                 RETURN i;
         END InsertChart;
         FUNCTION SaveToFile(filename VARCHAR2) RETURN BINARY_INTEGER IS
         BEGIN
             ordcom.InitArg();
             ordcom.SetArg(filename,'BSTR');

             i:=ordcom.Invoke(WorkBookToken, 'SaveAs', 1, DummyToken); -- 保存文件
             IF (i!=0) THEN
                 ordcom.GetLastError(err_src, err_desc, err_hpf, err_hpID);
                 raise_application_error(-20000,err_src || err_desc || err_hpf || err_hpID);
             END IF;
             RETURN i;
         END SaveToFile;
         FUNCTION CloseExcel RETURN BINARY_INTEGER IS
         BEGIN
             ordcom.InitArg();
             ordcom.InitArg();
             ordcom.SetArg(FALSE,'BOOL');
             i:=ordcom.Invoke(WorkBookToken, 'Close', 0, DummyToken);
             i:=ordcom.DestroyObject(WorkBookToken);
             ordcom.InitArg();
             i:=ordcom.Invoke(WorkBooksToken, 'Close', 0, DummyToken);
             i:=ordcom.DestroyObject(WorkBooksToken);
             i:=ordcom.Invoke(applicationToken, 'Quit', 0, DummyToken);

             -- 关闭所有句柄
             i:=ordcom.DestroyObject(WorkSheetToken);
             i:=ordcom.DestroyObject(WorkSheetToken1);
             i:=ordcom.DestroyObject(applicationToken);
             i:=ordcom.DestroyObject(ChartObjectToken);
             i:=ordcom.DestroyObject(Chart1Token);
             i:=ordcom.DestroyObject(hLines);
             i:=ordcom.DestroyObject(ChartObject1);
             i:=ordcom.DestroyObject(dummyToken);
             RETURN i;
         END CloseExcel;
      END oraExcel;


http://emag.csdn.net                         - 19 -                 2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》



    成功创建 oraExcel 包后,最后创建使用包的存储过程,实现把数据表里的字符型、日期型和

数值型分别传到 Excel 工作表里,对数值型数据进行统计和使用 Excel 中的图表。该过程具体操作

步骤为:

        创建 Excel 对象。

        建立表头,设置列宽。

        将游标数据传到工作表。

        画表格。

        设置字体属性。

        插入图表。

        保存为 Excel 格式文件,关闭 Excel 对象。



如下为 dp_toExcel 存储过程:


      CREATE OR REPLACE PROCEDURE dp_ToExcel IS
        CURSOR c1 IS SELECT ITS_ID,ITS_DATE,ITS_TOTAL FROM IT_SALE_TAB;
        n                  BINARY_INTEGER:=2;
        i                  BINARY_INTEGER;
        filename           VARCHAR2(255);
        cellIndex          VARCHAR2(40);
        cellValue          VARCHAR2(40);
        cellColumn         VARCHAR2(10);
        returnedTime        VARCHAR2(20);
        currencyvalue       DOUBLE PRECISION;
        dateValue           DATE;
        xlThin              BINARY_INTEGER:=2;
        xlEdgeLeft          BINARY_INTEGER:=7;
        xlEdgeTop           BINARY_INTEGER:=8;
        xlEdgeBottom        BINARY_INTEGER:=9;
        xlEdgeRight         BINARY_INTEGER:=10;
        xlInsideVertical    BINARY_INTEGER:=11;
        xlInsideHorizontal BINARY_INTEGER:=12;
      BEGIN
         i:=oraExcel.CreateExcelWorkSheet('');

         i:=oraExcel.setCellValues('A2', '序号', 'BSTR');
         i:=oraExcel.setCellValues('B2', '日期', 'BSTR');
         i:=oraExcel.setCellValues('C2', '销售', 'BSTR');


http://emag.csdn.net                            - 20 -            2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
         i:=oraExcel.setCellColWidth('B:B', 12.75,'CY');    -- 设置列宽
         i:=oraExcel.setCellColWidth('C:C', 12.75,'CY');
         n:=3;
         For c1_rec IN c1 LOOP
             cellColumn:=TO_CHAR(n);
             cellIndex:= 'A'||cellColumn;
             cellValue:= TO_CHAR(c1_rec.ITS_ID);
             i:=oraExcel.setCellValues(cellIndex, cellValue, 'BSTR');
             cellIndex:= 'B' || cellColumn;
             dateValue:=c1_rec.ITS_DATE;
             i:=oraExcel.setCellValues(cellIndex, dateValue, 'DATE');
             cellIndex:= 'C' || cellColumn;
             cellValue:=c1_rec.ITS_TOTAL;
             currencyValue:=cellValue;
             i:=oraExcel.setCellValuesReal(cellIndex, currencyValue, 'CY');
             n:=n+1;
         END LOOP;

         i:=oraExcel.setCellValues('A'||n,'合计','BSTR');
         i:=oraExcel.setCellValues('C'||n,'=SUM(C3:C'||to_char(n-1)||')','BSTR');

         -- 画表格
         i:=oraExcel.setCellLines('A1:C'||n,xlEdgeLeft,xlThin,'I2');
         i:=oraExcel.setCellLines('A1:C'||n,xlEdgeTop,xlThin,'I2');
         i:=oraExcel.setCellLines('A1:C'||n,xlEdgeBottom,xlThin,'I2');
         i:=oraExcel.setCellLines('A1:C'||n,xlEdgeRight,xlThin,'I2');
         i:=oraExcel.setCellLines('A1:C'||n,xlInsideVertical,xlThin,'I2');
         i:=oraExcel.setCellLines('A1:C'||n,xlInsideHorizontal,xlThin,'I2');

         -- 设置字体属性
         i:=oraExcel.setCellFont('A1:C1','Size',20,'I2');
         i:=oraExcel.setCellFont('A1:C1','Bold',1,'I2');

         i:=oraExcel.callMethod('A1:C1','Merge');                  -- 合并单元格
         i:=oraExcel.setCellValues('A1:C1','合计','BSTR');

         -- 插入图表
         i:=oraExcel.InsertChart(350,200,250,250,'C3:C'||TO_CHAR(n-1),'xlPie');
         SELECT TO_CHAR(SYSDATE, 'HH24MISS') INTO returnedTime FROM dual;
         filename:='D:testExcel' || returnedTime || '.xls';

         i:=oraExcel.SaveToFile(filename);    -- 保存文件
         i:=oraExcel.closeExcel();            -- 关闭对象
      END;




1.6. 小结

    本文介绍如何从 PL/SQL 中直接调用 C 程序的外部例程,并以操作 Excel 对象为示例。在调用

http://emag.csdn.net                          - 21 -                    2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

该外部例程时,有如下相关的限制:
        操作系统必需支持动态链接库(DLL)和共享库功能。
        监听器和 extproc 进程必须运行在数据库所在的同一台机子上,不支持远程数据库。
        extproc 唯一支持的是 C 例程,但可以通过先调用 C 外部例程去使用其它对象(如:COM
        对象)   。
    除了限制外,调用外部例程会引起额外的系统资源开销,在使用外部例程之前要考虑是否一

定要用到外部例程。




作者简介:

              姓名:陈思童

              网名:chanet

              CSDN 社区 Oracle 开发版主;

              熟悉数据库开发、Oracle 数据库接口设计、数据库管理。

  个人教育和成长经历:

  信息管理专业;大学毕业后一直从事以 Oracle 为主的开发工作。

  擅长的技术领域:

  数据库开发、软件规划、系统分析。

  研究方向:

      数据库管理、数据仓库、电子商务。

  目前的工作动态:

  广州某软件公司;负责后台设计、数据库接口技术支持、数据库开发与维护工作。

  个人Blog:http://blog.csdn.net/chanet

  MSN:cheasy@hotmail.com

  E-mail:chanet@oracle.com.cn OR     chanet@163.com




http://emag.csdn.net               - 22 -             2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


数据库复制

    最简单的创建只读实体化视图站点的方法


                                                本文作者: Kamus (kamusis@gmail.com )



    摘要:由于支持异构这一特点,Oracle 的高级复制通常被作为一种性价比超群的数据库同步

方案,但是由于 Oracle 高级复制的功能比较强大,所以配置步骤也显得有些麻烦。但是如果我们

的要求比较简单,比如说只有一个数据库用作日常业务,支持数据更新,另外一个数据库只需要

作一个同步的备份,最多支持只读的查询,那么其实只需要非常简单的步骤就可以实现这个目的。



    本文给出最简单的步骤用以创建一个实体化视图站点,定时刷新,获取主站点中指定表的变

化,这个实体化站点可以作为查询服务器使用。

    完整的配置步骤如下。对于支持数据更新的数据库我们称为主站点,对于同步的数据库我们

称为实体化站点。



1.1. 主站点上创建实体化视图日志表
    CREATE MATERIALIZED VIEW LOG ON kamus.account2004;



1.2. 实体化视图站点上创建公用数据库链接
    conn system/password


    CREATE PUBLIC DATABASE LINK orcl using 'ORCL';



1.3. 实体化视图站点上创建刷新组,本例中 3 分钟刷新
     一次
    conn system/password


    BEGIN
http://emag.csdn.net                   - 23 -             2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
         DBMS_REFRESH.MAKE (
           name => 'kamus.test_repg',
           list => '',
           next_date => SYSDATE,
           interval => 'SYSDATE + 3/(24*60)',     --此处的刷新时间可以根据需求调整
           implicit_destroy => FALSE,
           rollback_seg => '',
           push_deferred_rpc => TRUE,
           refresh_after_errors => FALSE);
    END;
    /



1.4. 实体化视图站点上创建用户私有数据库链接
    conn kamus/password


    CREATE DATABASE LINK orcl CONNECT TO kamus IDENTIFIED BY password;



1.5. 实体化视图站点上创建实体化视图
    conn kamus/password


    CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY AS SELECT
* FROM     KAMUS.ACCOUNT2004@orcl;



1.6. 实体化视图站点上将创建的视图加入刷新组
    conn kamus/password


    exec DBMS_REFRESH.ADD(name => 'kamus.TEST_REPG', list => 'kamus.ACCOUNT2004', lax
=> TRUE);



1.7. 测试

    在主站点中更新 ACCOUNT2004 表,过 3 分钟检查实体化试图站点中的视图,发现更新已经

复制成功。



1.8. 总结

    总结一下建立只读实体化视图站点的最简单方法:
http://emag.csdn.net                     - 24 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

         不需要创建其它的任何用户,比如复制环境中需要的传播者,刷新者,接收者等等

         不需要创建任何复制组

         不需要生成任何复制对象,不需要生成任何对象的复制支持



1.9. 附录

创建实体化视图产生ORA-600 [ksmovrflow], [kkznxddl.begin]错误的解决方法



如果测试环境中的 master site 是 Oracle10g,MV site 是 Oracle9.x 或者 8.1.x,当在 MV site 上创建

快速刷新的实体化视图时,可能会报 ORA-600 错误。
    SQL> CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY   AS
SELECT * FROM    KAMUS.ACCOUNT2004@orcl;


    CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY AS SELECT
* FROM   KAMUS.ACCOUNT2004@orcl


    ORA-00600: internal error code, arguments: [ksmovrflow], [kkznxddl.begin], [], [],
[], [], [], []



这是Oracle10g的一个bug(Bug编号:3508674),只有当在Oracle8 或者 9 中创建基于Oracle10g的

实体化视图时才会发生。这个Bug在 10.1.0.3 Server Patch Set中被修复。



原因:

Oracle10g 的 master table 中创建主键时候显式指定了主键的名称。比如执行了类似下面的命令
    alter table table_name add constraint < constraint name> primary key (< col>);



解决方法:

删除这个主键,然后创建一个不指定名称的主键,由 Oracle 自动命名,如下:
    alter table ACCOUNT2004 add primary key(OCCURTIME, ACCTID, CURRENCYID);



这样产生的主键名称就变成 SYS_CXXXX。之后重新在 MV site 上创建实体化视图即可。




http://emag.csdn.net                       - 25 -             2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

作者简介:


                 张乐奕,网名 kamus



                 曾任 ITPUB Oracle 认证版版主,现任 itpub Oracle 管理版版主。




现任职于北京某大型软件公司,首席DBA,主要负责证券行业的全国十数处核心交易系统数据库管

理及维护工作。

热切关注Oracle技术和其它相关技术,出没于各大数据库技术论坛,目前是中国最大的Oracle技

术论坛www.itpub.net的数据库管理版版主。

    阅读更多技术文章和随笔可以登录我的个人blog。

    http://blog.dbform.com。




http://emag.csdn.net              - 26 -         2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》




         Oracle 高级复制冲突解决机制的研究

 —— dbms_rectifier_diff 及手动解决 Oracle 高级复制中的冲突


                                                         本文作者: eygle (eygle.com@gmail.com )



    摘要:本文简要探讨 dbms_rectifier_diff 包的机制及如何手动解决 Oracle 高级复制中的冲突。



    关于 dbms_rectifier_diff 的使用请参考:

http://www.eygle.com/archives/2005/01/eoadbms_rectifi.html



    实际上 Oracle 的 dbms_rectifier_diff.DIFFERENCES 过程,内部操作就是执行两个 minus 操作

    把两边的差异记录下来,作为冲突解决的数据。



    这部分后台操作可以通过跟踪 Oracle 进程得到:


    SQL> alter session set events '10046 trace name context forever,level 12';


    Session altered.


    Elapsed: 00:00:00.02
    SQL> begin dbms_rectifier_diff.DIFFERENCES(
      2 SNAME1                           =>'HAWA',
      3 ONAME1                           =>'TEST',
      4 REFERENCE_SITE                     =>'AVATAR.COOLYOUNG.COM.CN',
      4 SNAME2                           =>'HAWA',
      6 ONAME2                           =>'TEST',
      7 COMPARISON_SITE                    =>'AUTHAA.COOLYOUNG.COM.CN',
      8 WHERE_CLAUSE                      =>NULL,
      9 COLUMN_LIST                       =>NULL,
     10 MISSING_ROWS_SNAME                  =>'HAWA',
     11 MISSING_ROWS_ONAME1                 =>'MISSING_ROWS_TEST',
     12 MISSING_ROWS_ONAME2                 =>'MISSING_LOCATION_TEST',

http://emag.csdn.net                          - 27 -                 2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
     13 MISSING_ROWS_SITE                   =>'AVATAR.COOLYOUNG.COM.CN',
     14 MAX_MISSING                        =>500,
     15 COMMIT_ROWS                        =>100
     16 );
     17 end;
     18 /


    PL/SQL procedure successfully completed.


    Elapsed: 00:00:01.97
    SQL> alter session set events '10046 trace name context off';



    从跟踪文件中我们可以清晰的看到(注意你所定义的所有参数在此都会有所体现):

    首先是一个正向 Minus
    DECLARE
       row_count            BINARY_INTEGER := 0;
       missing_rows         BINARY_INTEGER := 0;
       arowid            ROWID;


       CURSOR c
       IS
            SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP",
                    "VC2USERNAME"
              FROM "HAWA"."TEST"
            MINUS
            SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP",
                    "VC2USERNAME"
              FROM "HAWA"."TEST"@authaa.coolyoung.com.cn;
    BEGIN
       FOR r IN c
       LOOP
            missing_rows := missing_rows + 1;


            IF missing_rows > 500
            THEN
              COMMIT;
              EXIT;
            END IF;


            INSERT INTO "HAWA"."MISSING_ROWS_TEST"
                        ("DATLOGONTIME", "NUMGENDER", "NUMSTATUS",
                        "NUMUSERID", "VC2IP", "VC2USERNAME"
                        )

http://emag.csdn.net                          - 28 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                  VALUES (r."DATLOGONTIME", r."NUMGENDER", r."NUMSTATUS",
                        r."NUMUSERID", r."VC2IP", r."VC2USERNAME"
                        );


           SELECT ROWID
            INTO arowid
            FROM "HAWA"."MISSING_ROWS_TEST"
           WHERE (      datlogontime = r."DATLOGONTIME"
                    OR (datlogontime IS NULL AND r."DATLOGONTIME" IS NULL)
                   )
              AND (     numgender = r."NUMGENDER"
                    OR (numgender IS NULL AND r."NUMGENDER" IS NULL)
                   )
              AND (     numstatus = r."NUMSTATUS"
                    OR (numstatus IS NULL AND r."NUMSTATUS" IS NULL)
                   )
              AND (numuserid = r."NUMUSERID")
              AND (vc2ip = r."VC2IP" OR (vc2ip IS NULL AND r."VC2IP" IS NULL))
              AND (     vc2username = r."VC2USERNAME"
                    OR (vc2username IS NULL AND r."VC2USERNAME" IS NULL)
                   );


           INSERT INTO "HAWA"."MISSING_LOCATION_TEST"
                        (present, absent, r_id
                        )
                  VALUES ('AVATAR.COOLYOUNG.COM.CN', 'AUTHAA.COOLYOUNG.COM.CN',
                        arowid
                        );


           row_count := row_count + 1;


           IF row_count >= 100
           THEN
              COMMIT;
              row_count := 0;
           END IF;
       END LOOP;


       COMMIT;
    END;

    其次是一个反向 Minus
    DECLARE
       row_count            BINARY_INTEGER := 0;
       missing_rows         BINARY_INTEGER := 0;

http://emag.csdn.net                          - 29 -            2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
       arowid            ROWID;


       CURSOR c
       IS
            SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP",
                    "VC2USERNAME"
              FROM "HAWA"."TEST"@authaa.coolyoung.com.cn
            MINUS
            SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP",
                    "VC2USERNAME"
              FROM "HAWA"."TEST";
    BEGIN
       FOR r IN c
       LOOP
            missing_rows := missing_rows + 1;


            IF missing_rows > 500
            THEN
              COMMIT;
              EXIT;
            END IF;


            INSERT INTO "HAWA"."MISSING_ROWS_TEST"
                        ("DATLOGONTIME", "NUMGENDER", "NUMSTATUS",
                         "NUMUSERID", "VC2IP", "VC2USERNAME"
                        )
                   VALUES (r."DATLOGONTIME", r."NUMGENDER", r."NUMSTATUS",
                         r."NUMUSERID", r."VC2IP", r."VC2USERNAME"
                        );


            SELECT ROWID
              INTO arowid
              FROM "HAWA"."MISSING_ROWS_TEST"
            WHERE (      datlogontime = r."DATLOGONTIME"
                     OR (datlogontime IS NULL AND r."DATLOGONTIME" IS NULL)
                    )
              AND (     numgender = r."NUMGENDER"
                     OR (numgender IS NULL AND r."NUMGENDER" IS NULL)
                    )
              AND (     numstatus = r."NUMSTATUS"
                     OR (numstatus IS NULL AND r."NUMSTATUS" IS NULL)
                    )
              AND (numuserid = r."NUMUSERID")
              AND (vc2ip = r."VC2IP" OR (vc2ip IS NULL AND r."VC2IP" IS NULL))
              AND (     vc2username = r."VC2USERNAME"
http://emag.csdn.net                         - 30 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
                    OR (vc2username IS NULL AND r."VC2USERNAME" IS NULL)
                   );


           INSERT INTO "HAWA"."MISSING_LOCATION_TEST"
                        (present, absent,
                        r_id
                        )
                  VALUES ('AUTHAA.COOLYOUNG.COM.CN', 'AVATAR.COOLYOUNG.COM.CN',
                        arowid
                        );


           row_count := row_count + 1;


           IF row_count >= 100
           THEN
             COMMIT;
             row_count := 0;
           END IF;
       END LOOP;


       COMMIT;
    END;



    经过这两个步骤的操作,Oracle 定位了冲突数据。



    可是注意,如果在解决这个问题时你没有挂起复制,Oracle 得到的数据可能是存在问题的。

    而且,如果你不指定 column list,那么两边的数据可能会因为某些特殊字段(如时间字段)的特殊

处理而存在差异。



    那么这时候手工介入不可避免。



    我们首先先把两个重要参数的用法说明一下。

    一个是 WHERE_CLAUSE,另外一个是 COLUMN_LIST。



    WHERE_CLAUSE 用于限定进行差异比较的范围,这可以极大的缩减结果集的数量,使用索

引加快访问速度等。

    比如我这里使用 NUMGENDER=1,只比较性别为"女"这一部分用户数据。

http://emag.csdn.net                        - 31 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》



    COLUMN_LIST 用于限定比较字段,如果你能通过某个字段,如主键等确定数据差异,那么

你完全可以只比较单个字段。

    而且显然可以轻易通过全索引扫描来完成比较,加快比较速度。

    我这里使用 NUMUSERID,用户 ID 来比较。

    但 是 注 意 , 这 样 的 比 较 结 果 中 将 只 包 含 NUMUSERID 信 息 , 当 然 我 们 可 以 轻 易 通 过

NUMUSERID 和原表的比较补全 MISSING_ROWS_TEST 表的信息。




    begin dbms_rectifier_diff.DIFFERENCES(
    SNAME1                    =>'HAWA',
    ONAME1                    =>'TEST',
    REFERENCE_SITE              =>'AVATAR.COOLYOUNG.COM.CN',
    SNAME2                    =>'HAWA',
    ONAME2                    =>'TEST',
    COMPARISON_SITE             =>'AUTHAA.COOLYOUNG.COM.CN',
    WHERE_CLAUSE               =>'NUMGENDER=1',
    COLUMN_LIST                =>'NUMUSERID',
    MISSING_ROWS_SNAME          =>'HAWA',
    MISSING_ROWS_ONAME1         =>'MISSING_ROWS_TEST',
    MISSING_ROWS_ONAME2         =>'MISSING_LOCATION_TEST',
    MISSING_ROWS_SITE           =>'AVATAR.COOLYOUNG.COM.CN',
    MAX_MISSING                =>500,
    COMMIT_ROWS                =>100
    );
    end;
    /



    这段代码供参考。



    Ok,我们继续前面的讨论。

    我们提到,如果存在差异,通常需要手工介入。



    清楚了 DIFFERENCES 的原理,实际上我们完全可以手工来完成这个过程。

    以下是我的手工操作步骤,目的是为了准确性及减轻数据库压力:



http://emag.csdn.net                    - 32 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

        首先创建一个 ID 差异表

    这个表不是必须的,这里是为了清晰
    SQL> create table hawa.prof as select NUMUSERID from hawa.hw_user where 1=0;


    Table created.


    Elapsed: 00:00:00.16



        根据主键找到差异记录

    注意这里取决于你的数据库产生差异的原因,我的差异由于初始数据不同步,即 A 全包含 B

并且,A>B。
    SQL> insert into hawa.prof
      2 select * from
      3 (
      4 select NUMUSERID from hawa.HW_USERPROFILE
      5 minus
      6 select NUMUSERID from hawa.HW_USERPROFILE@authaa)
      7 /


    263 rows created.


    Elapsed: 00:00:32.49



        创建记录表
    SQL> create table hawa.missing_rows_hw_userprofile
      2 as
      3 select * from hawa.hw_userprofile where 1=0;


    Table created.


    Elapsed: 00:00:00.12




        创建位置(Location)表

    注 意 这 里 Oracle 需 要 记 录 缺 失 方 向 , 和 具 体 记 录 的 ROWID , 这 个 ROWID 来 自

missing_rows_hw_userprofile。
    SQL> create table hawa.MISSING_LOC_hw_userprofile (
      2 present VARCHAR2(128),
      3 absent VARCHAR2(128),
http://emag.csdn.net                   - 33 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
      4 r_id ROWID);


    Table created.


    Elapsed: 00:00:00.04



          根据差异信息查询到完整信息
    SQL> insert into hawa.missing_rows_hw_userprofile
      2 select * from hawa.hw_userprofile where NUMUSERID in
      3 (select * from hawa.prof);


    263 rows created.


    Elapsed: 00:00:00.06
    SQL> commit;


    Commit complete.


    Elapsed: 00:00:00.02




          构造位置信息

    注意这里的方向信息及 ROWID 信息。
    SQL> insert into hawa.MISSING_LOC_hw_userprofile
      2     select     'AVATAR.COOLYOUNG.COM.CN','AUTHAA.COOLYOUNG.COM.CN',rowid   from
hawa.missing_rows_hw_userprofile;


    263 rows created.


    Elapsed: 00:00:00.00
    SQL> commit;


    Commit complete.


    Elapsed: 00:00:00.06




          纠正数据冲突
    SQL> BEGIN DBMS_RECTIFIER_DIFF.RECTIFY(
      2 SNAME1                        =>'HAWA',
      3 ONAME1                        =>'HW_USERPROFILE',

http://emag.csdn.net                       - 34 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
      4 REFERENCE_SITE              =>'AVATAR.COOLYOUNG.COM.CN',
      5 SNAME2                     =>'HAWA',
      6 ONAME2                     =>'HW_USERPROFILE',
      7 COMPARISON_SITE             =>'AUTHAA.COOLYOUNG.COM.CN',
      8 COLUMN_LIST                =>NULL,
      9 MISSING_ROWS_SNAME           =>'HAWA',
     10 MISSING_ROWS_ONAME1          =>'MISSING_ROWS_HW_USERPROFILE',
     11 MISSING_ROWS_ONAME2          =>'MISSING_LOC_HW_USERPROFILE',
     12 MISSING_ROWS_SITE            =>'AVATAR.COOLYOUNG.COM.CN',
     13 COMMIT_ROWS                 =>100
     14 );
     15 END;
     16 /


    PL/SQL procedure successfully completed.


    Elapsed: 00:00:03.53




        验证结果
    SQL> select count(*) from hawa.HW_USERPROFILE;


      COUNT(*)
    ----------
       1746300


    Elapsed: 00:00:02.22
    SQL> select count(*) from hawa.HW_USERPROFILE@authaa;


      COUNT(*)
    ----------
       1746300


    Elapsed: 00:00:00.21


    SQL> select count(*) from hawa.HW_USERPROFILE;


      COUNT(*)
    ----------
       1746300


    Elapsed: 00:00:00.59


    SQL>select count(*) from hawa.HW_USERPROFILE@authaa;
http://emag.csdn.net                   - 35 -               2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


      COUNT(*)
     ----------
       1746300


     Elapsed: 00:00:00.20
     SQL> select NUMUSERID from hawa.HW_USERPROFILE
      2 minus
      3 select NUMUSERID from hawa.HW_USERPROFILE@authaa   ;


     no rows selected


     Elapsed: 00:00:23.51
     SQL>




作者简介:


                  盖国强,网名 eygle



                  曾任 ITPUB MS 版版主,现任 itpub Oracle 管理版版主.




       曾任职于某国家大型企业,服务于烟草行业,开发过基于 Oracle 数据库的大型 ERP 系

统,属国家信息产业部重点工程.同时负责 Oracle 数据库管理及优化,并为多家烟草企业提供

Oracle 数据库管理、优化及技术支持.

       目前任职于北京某电信增值业务系统提供商企业,首席 DBA,负责数据库业务.管理全国

30 多个数据库系统。项目经验丰富,曾设计规划及支持中国联通增值业务等大型数据库系统.

       实践经验丰富,长于数据库诊断、性能调整与 SQL 优化等。对于 Oracle 内部技术具有

深入研究。

       高级培训讲师,培训经验丰富,曾主讲 itpub dba 培训及 itpub 高级性能调整等主要课

程.

      《Oracle 数据库 DBA 专题技术精粹》一书的主编及主要作者.

       你可以在http://www.eygle.com上找到关于作者的更多信息.




http://emag.csdn.net                    - 36 -                 2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》


数据库高可用性

                       SharePlex for Oracle


                                             本文作者: Quest Software China




1.1. 前言

    在企业信息化进程不断加快的今天,保持业务的连续性是企业用户进行数据存储时必须考虑

的重要方面。灾难的出现可能导致生产停顿、客户满意度降低,减少企业的竞争力。如何安全、

可靠、完整地保存数据,实现系统的灾难恢复是市场竞争的需要,更是进一步提高服务水平和改

善服务质量、提升业务支撑能力的重要技术手段。

    目前,很多厂家都提供容灾保护的产品,主要包括基于存储、逻辑卷、主机、数据库物理方

式和数据库逻辑方式的各种复制技术。根据复制层面的不同,实现的技术以及容灾效果各不相同。

Quest Software 的 SharePlex for Oracle 通过数据库逻辑层的复制技术,可以方便地实现基于 Oracle

数据库的容灾保护,具有对源系统资源占用少,对网络资源占用少,支持异构环境和不同的复制

拓扑,保持事物一致性的特点。在开放异构环境、异地容灾、容灾系统可访问的环境中具有非常

大的优势。

     通过 SharePlex for Oracle,可以帮助企业建立一个全面的、整体的容灾方案,最大限度地保证

业务系统的连续性和业务数据的可恢复性。



1.2. 高可用容灾方案设计

1.2.1. 高可用容灾系统的影响因素

    影响应用系统可用性主要有三方面的因素,计划外的系统停机、计划内的维护操作和灾难恢

复。




http://emag.csdn.net            - 37 -           2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.2.2. 计划外的系统停机

    计划外的系统停机指由于应用系统故障导致的系统不可用。减少计划外的停机时间是应用系

统设计人员和管理人员面临的主要任务,虽然每个业务系统都在硬件、软件和人员方面投入很多,

但每年计划外的停机时间还是不可避免的发生,造成了很多不可避免的经济损失。一般来说,计

划外的系统停机主要是由于以下原因引起的。

    人为错误。如用户具有过多的权限,从而可以访问没有被授权的一些数据。或者数据库管理

    人员过度劳累导致的错误。

    硬件/软件出错。硬件和软件失败是不可避免的现象,而且随着数据库系统使用年限的增加而

    变得更加脆弱。通常由于硬件/软件出错所引起的故障包括应用程序出错、数据库出错、操作

    系统故障,如操作系统死机等以及硬件故障,如硬盘或网卡损坏等。

    环境失败。环境失败指由于外部环境改变导致系统不可用或无法有效地进行数据库管理。如

    断电,工人罢工等等。



1.2.2.1. 计划内的维护操作

    系统操作人员经常提到的一个术语就是“维护”。大多数维护操作会影响到系统的可用性和性

能。由于进行主动系统维护所引起的停机时间被称为计划内停机时间。对于每个数据库应用来说,

每年或每月都需要一定的计划内停机时间,因为停机时间可以控制,停机操作对系统的影响也可

以预先通知到用户,因而计划内停机时间虽然发生频繁,对系统的影响可以控制在一定范围。



1.2.2.2. 灾难恢复

    对于高可用需求的应用系统来说,自然灾害与人为灾害始终存在。自然原因引起的灾难包括

地震、洪水、火灾、飓风、恐怖活动、战争、暴乱活动等,人为因素导致的数据库不可用包括故

意破坏。这些灾难发生的概率非常低,但是如果一旦发生,对严重依赖于数据的企业是致命的打

击,甚至导致企业无法继续运营。

    在灾难发生的情况下,数据恢复成为高可用性管理的首要任务,数据备份、特别是异地数据

备份是成功实现灾难恢复的核心。企业需要在保证业务数据恢复的情况下保持业务系统的连续性。




http://emag.csdn.net   - 38 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.2.3. 高可用容灾系统的建设目标

    系统的容灾和高可用方案必须能够应付所有可能引起计算机系统失效的问题。应用系统高可
用性和容灾方案需要满足两方面的要求:

    1.业务系统的连续性

    保持业务系统的连续性,意味着无论是由于硬件,软件或电源的失效都不应中断信息中心的
处理工作;实现业务的连续性需要减少或消除计划外停机时间,控制计划外停机时间对系统的影
响,在灾难发生时间进行业务系统的快速接管,这些主要通过各个层次的冗余技术实现的。

    2.业务数据的可恢复性

业务数据的可恢复性从本质上来说是业务系统连续性的一个子集。如果数据出现问题而不能恢复,

业务系统的连续性无从谈起。因为数据对严重依赖于信息系统的企业非常重要,数据的可恢复性

一直是高可用性系统的一个重点考虑因素。业务数据的可恢复性是通过数据备份和冗余的数据拷

贝完成的。数据库复制和硬件复制都是用于这个环境的一些成熟技术。业务数据的可恢复性主要

考虑因素为备份数据的安全性,需要确保在任何情况下,包括容灾发生时备份数据都可以有效地

进行恢复。同时,数据丢失也是一个非常重要的评价指标。



1.2.4. 建设容灾系统的考虑因素

    因为要建立整个应用系统的冗余备份,容灾系统是一个非常昂贵的系统,在容灾系统建设时
需要考虑以下因素:

         容灾距离:

    根据灾备中心建设的目的不同,灾备中心的建设需要考虑灾备中心的距离。一般来说,容灾
距离有本地和同城、异地三种方式。

    异地容灾方案中,灾备中心和主中心的距离较远,如北京到上海。异地容灾可以有效地防止
由于本地灾难发生引起数据损失,但是实施成本很高、为了保障业务系统的性能一般采用同步数
据拷贝方式,这样会存在一定的数据损失,同时将应用系统切换到灾备中心的工作也非常繁琐。
一般来说,异地灾备中心建设的主要目的提供业务数据的恢复能力。

    同城容灾方案中,灾备中心和主中心距离在几十公里以内。同城容灾可以有效地提供业务数
据的恢复能力以及应用快速接管能力。根据业务系统对数据访问以及数据丢失的需求,数据复制
可以采用同步或异步两种方式。

    同地容灾指灾备系统和主中心在一个地理位置。一般来说,它可以和现有的其他可用性技术,
如 Cluster 结合,提供更高级别的高可用性。同时,很多同地容灾解决方案提供灾备中心的数据访

http://emag.csdn.net   - 39 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
问能力。

    为了有效地进行容灾,很多关键的业务系统建立两个系统,同城灾备中心和异地灾备中心,
同城灾备中心由生产系统采用同步方式进行数据复制,异地灾备中心由同城灾备中心采用异步方
式进行数据复制。

         数据丢失

    企业能忍受的数据丢失和具体处理的业务有关。例如:财务系统的数据很难承受任何损失,
而电信营帐系统在灾难发生时可以允许少量的数据丢失。目前,虽然有很多方案可以做到“零数据
丢失“,但企业往往为此支付高昂的费用,生产系统的性能也会受到很大影响。从业务的角度企业
能够承受德考虑数据丢失问题可以帮助企业在容灾方案上做出适合企业自身特点的选择。

         应用切换时间

    容灾系统建设的一个重要目的是保障业务系统的连续性。在灾难发生或业务系统出现问题时
间,将应用快速地切换到灾备系统可以最大程度地减少系统的停计时间。当灾难发生,启用灾备
中心需要采取一系列的措施。如将网络、电话线路切换到新的地点,启动操作系统、数据库,进
行应用程序的切换等等。一般来说,容灾系统的切换时间应该控制到 30 分钟以内。

         主系统的可恢复性

    主系统的可恢复性主要指数据的恢复,将应用切换灾备系统后,业务的连续性得以保持,主
系统的恢复时间应该控制在一天到几天之内。数据恢复的关键问题在于数据的可恢复性,以及恢
复过程中如何和灾备中心的数据保持一致。

         目标系统的可访问性

    目标数据可访问能够提高容灾系统的投资回报,增加容灾系统的利用价值。企业可以将目标
系统作为报表查询、统计分析等系统的数据源,减轻源系统的压力,使投资变为可用,而不是单
存的冷备闲置。同时,目标数据的在线使用可以保障数据的准确性,从而避免容灾系统长期冷备,
数据错误而无人发现的情况,能够确保容灾系统在灾难发生时被有效接管,进行数据恢复。

         对源系统的影响。

     灾备中心的建设是对现有系统的扩展和补充,不能因为灾备中心影响当前业务系统的性能,
导致系统的可用性降低。

         网络资源的使用。

     网络资源的使用对于容灾系统特别是异地容灾系统非常重要。在网络上传输的数据量大小直
接决定数据传输的实时性,同时,网络资源占用会影响灾备中心后期的网络使用费用。

         容灾环境的开放性。

    组成数据库应用系统的环境非常复杂,主机、存储、数据库是容灾环境的三个主要组件,支
持开放环境,例如容灾系统支持不同的操作系统和数据库、不同的磁盘阵列、不同的主机系统会
有效地适应未来的扩展需求,充分保护投资。
http://emag.csdn.net   - 40 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

实施成本是在充分评估了上述内容后需要考虑的又一个重要因素。事实上,在建立容灾系统时,

一个对业务系统没有任何影响、没有任何数据损失、容灾距离足够远的方案是很难实现的。企业

需要了解自己的需求,建立适合自身特点的容灾系统。双数据中心环境下的有效冗余和网络结构



1.2.5. 容灾系统的实现技术

1.2.5.1. 基于磁带拷贝的传统灾难备份方式

    利用磁带拷贝进行数据备份和恢复是最常见的传统灾难备份方式。这些磁带拷贝通常都是按
天,按周或按月进行组合保存的。

    使用这种方式的数据拷贝通常是存储在盘式磁带或盒式磁带上,并存放在远离基本处理系统
的某个安全地点。存储到安全地点的磁带拷贝,其上的数据已有数小时的延迟,而在灾难或各种
故障出现系统需要立即恢复,必须将磁带提取出来,并运送到恢复地点,通常还要滞延几个小时。

基于磁带拷贝方式的传统灾难备份方式有着明显的缺陷,越来越不适合用户不断发展的业务系统

的需要。其备份和恢复过程非常复杂,数据延迟较大,磁带管理困难,数据恢复必须按照正确的

顺序,出错的可能性也较大。



1.2.5.2. 数据库方式

    数据库复制是目前最流行的高可用解决方案。每种数据库系统来实现的机制和方式略有不同,
但都包括逻辑复制和物理复制两种方式:

    逻辑复制指针对数据库的逻辑层数据进行复制,复制的基本单位为数据库表以及表中所有的
数据,复制时采用标准的 TCP/IP 协议。这种复制方法的好处是复制的数据量少,网络资源占用低,
在复制的过程中目标数据库可以被访问,企业可以将目标系统用于报表和查询系统。同时因为目
标数据库处于启动状态,接管时不需要重新启动数据库,接管可以接近实时。

    物理复制方法主要通过日志文件的传送和应用实现的。数据库交易的复制机制利用日志的这
种特性,在生产中心将日志传输到灾备中心;如果灾备中心的数据库结构和生产中心的数据库结
构保持一致,则灾备中心的数据库对日志中记载的交易执行前滚操作,即实现了对灾备中心数据
库数据的更新。

    数据库级别的复制可以支持计划内停机时间、计划外的停机时间和应用可以允许一些损失的

情况下进行灾难恢复。




http://emag.csdn.net   - 41 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.2.5.3. 服务器卷方式

    服务器卷方式复制嵌入到操作系统的卷管理系统中,卷发生的变化分为结构的变化和卷内容
的变化。这种复制方式可以复制卷内容的变化。

    服务器卷方式有两种复制方式,同步方式和异步方式。同步方式采用数据库两阶段提交的方
法,对源系统的影响非常大。异步方式从数据的一致性保障方面存在问题。

    由于卷复制部件使用服务器 CPU、Memory 资源,使用标准的 TCP/IP 网络,对业务的正常运
行产生的较大的性能影响。

    使用服务器卷方式进行复制,必须使用专用的卷管理软件,整个应用系统的结构需要根据卷
管理的要求经过严格的设计和重新划分,同时,在后期的维护过程中也需要对卷结构的变化进行
同步的维护,从而增加实施和维护方面的一些困难。

服务器卷方式复制对服务器的硬件平台、数据库版本有严格限制,局限于主机同构环境。



1.2.5.4. 智能存储系统方式

    智能存储方式利用磁盘系统自身的处理能力,通过磁盘系统之间的通道连接复制磁盘系统内
的数据更新,从而在异地中心保存生产数据的记录。利用磁盘复制可以独立于服务器、操作系统、
卷管理系统、数据库、文件系统、中间件、应用程序。

    和服务器卷方式一样,智能存储两种复制方式,同步方式和异步方式。同步方式采用数据库
两阶段提交的方法,对源系统的影响非常大。异步方式从数据的一致性保障方面存在问题。

    智能存储系统方式复制使用存储上的 CPU 资源,但对 IO 资源的消耗比较大。这种方式复制
速度很快,但这种复制方式对存储依赖非常强,主备服务器必须使用同样的存储设备,依赖于专
有网络。因为在存储级进行复制,目标数据库处于不可用状态。当需要应用切换时,必须停止复
制过程,Mount 复制卷组,将操作系统启动,启动数据库,进行数据库恢复。所有这些工作一般
手工进行,需要花费一定的时间。

    采用智能存储系统方式进行复制,源系统和目标系统的硬件平台、操作系统、数据库版本必

须一致。复制的内容包括所有底层数据,占用的网络带宽较高。而且目标系统无法访问。



1.3. SharePlex for Oracle 介绍

    目前,很多厂家都提供容灾保护的产品,主要包括基于存储、逻辑卷、主机、数据库物理方

式和数据库逻辑方式的各种复制技术。根据复制层面的不同,实现的技术以及容灾效果各不相同。

Quest Software 的 SharePlex for Oracle 通过数据库逻辑层的复制技术,可以方便地实现基于 Oracle
http://emag.csdn.net            - 42 -           2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

数据库的容灾保护,具有对源系统资源占用少,对网络资源占用少,支持异构环境和不同的复制

拓扑,保持事物一致性的特点。在开放异构环境、异地容灾、容灾系统可访问的环境中具有非常

大的优势。



1.3.1. SharePlex for Oracle 结构

    基本结构

    下图所示为 SharePlex for Oracle 的基本结构,其中涉及较多的技术细节。




                       图 1-1   Shareplex 基本结构

    数据捕获

    SharePlex for Oracle 中由捕获进程来收集发生变化的数据,此进程的独特之处在于它几乎不对
生产数据库带来任何开销。

    数据传输

    SharePlex 结合其自己的网络协议和 TCP/IP 协议来完成源和目标系统之间的数据传输。其相
关的进程确保数据的正确接收和网络数据包的正确顺序,从而提供网络传输冗余,确保数据的完
整。整个数据传输过程无需其它的中间件。

    应用数据

    应用进程将传送到目标系统中的信息转化为 SQL 语句,然后采用标准的 SQL*Plus 方式将 SQL
语句发送给 Oracle 执行。

    SharePlex 能够实现精确复制的一个重要原因就是其能保证从源数据库到目标数据库的 Oracle

读一致性,不但按顺序复制事务,而且也复制上下文信息。由于 SharePlex 将源数据库中发生变化

http://emag.csdn.net             - 43 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

的全部事务信息都复制到目标数据库中,因此 SharePlex 复制方案用于灾难恢复系统中是足够可靠

的。



1.3.2. SharePlex for Oracle 配置方案

     SharePlex 提供多种不同的配置方式以满足高可用性和负载均衡需求。主要包括:

         单向复制

     SharePlex 可以将源系统的数据实时复制到目标系统,从而建立一个可以被访问的即席查询和
报表系统。目标系统可以是源系统的全集和子集。通过将查询和报表系统放在不同的数据库实例
中运行,可以平衡服务器负载并提高 OLTP 类生产系统的性能。




         高可用性

     保证数据高可用性和数据库系统能够从灾难中迅速恢复是一个非常具有挑战性的工作。
SharePlex for Oracle 可以通过 LAN 或 WAN 进行复制,这样当生产环境出现紧急事件或要进行例
行维护时,可以将应用切换到复制数据库中。有了生产数据库的实时拷贝,用户可以保证应用系
统 7*24 不间断运行的情况下进行维护工作,如进行操作系统和数据库的升级等等。




         分布处理

     多数据源配置允许你将不同的用户分布到不同的服务器,让每个数据库能够反映其他数据库
的变化。在这种配置模式下,SharePlex 采用必要的冲突处理机制来解决可能发生的冲突。




         广播和集中复制

     SharePlex for Oracle 通过 LAN 或 WAN 进行实时复制,将生产数据库中的数据拷贝到需要它
们的地方。对广播复制来说,远程用户可以访问这些实时数据而不用登录生产服务器。因此,提
高了网络性能和生产环境下的 OLTP 应用的性能。




http://emag.csdn.net          - 44 -         2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》




         企业环境的数据分布

    SharePlex 支持层叠复制,可以向不是直接相连的数据库复制数据。使用这种配置,可以在远
程数据库间进行复制(如从北京到上海)。SharePlex 支持多种复杂的场景来满足复制需求。




1.3.3. Shareplex for Oracle 特点

1.3.3.1. 快速精确和低负载

    SharePlex 是非常快速的,同时保证了复制数据的精确性。在源数据库一端,SharePlex 严格地

遵守读一致性模式。在目标数据库一端,SharePlex 使用标准 SQL 提交事务,并保证操作次序和会

话上下文的一致。

    基于 Log 的复制方式对源数据库和系统所带来资源开销非常小,因为复制操作只是读取操作

系统的日志文件,同时通过 TCP/IP 方式而不是采用中间件方式传输只发生改变的数据也使网络负

载降至最低。



1.3.3.2. 可扩展及全面

    每秒钟可针对数千个表复制超过一千个以上事务的处理能力意味着 SharePlex 可以处理企业级

的业务数据,可以满足企业大数据量的吞吐需求。实际环境中的吞吐速率是受服务器性能、网络

带宽和事务的复杂程度所影响的。

    SharePlex 提供的完全复制程度是其它软件复制工具所不具备的。SharePlex 支持带长列的表、
http://emag.csdn.net        - 45 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

带参照完整性约束的表、没有主键的表、序列等等的复制。此外,SharePlex 复制 ALTER TABLE

等命令,使它可以不需要其它软件复制工具就复制 DDL 活动。



1.3.3.3. 灾难恢复

    SharePlex 在设计时已经将性能和容灾因素考虑在内。SharePlex 可以容忍实例失败、系统失败

和网络失败。一般情况下,在源系统中运行的事务一旦被写入 log,SharePlex 立即将其发送到目标

系统。然而,如果发生问题,SharePlex 可以在源系统或目标系统进行事务排队(为了最小化对源系

统的影响,排队位于 Oracle 源实例之外)。例如,如果网络宕掉或目标系统宕掉,SharePlex 将源系

统中的事务排队。当网络或系统恢复后,SharePlex 将自动提交被排队的数据并清空队列文件。



1.3.3.4. 灵活配置和简洁管理

    SharePlex 可以被灵活配置,以支持各种复制策略。包括单向复制、双向复制、广播复制、集

中复制及多层复制等。

    SharePlex 是独立的软件,不需要修改与数据库进行交互的应用程序和数据库本身。因此,安

装非常简洁。配置和改变复制策略不影响源数据库系统中的生产活动。管理员可以用 Windows 界

面或服务器端的命令行管理和监控复制操作的各个方面。



1.3.4. SharePlex for Oracle 适用场合

    应用容灾

    企业开始比以往任何时候更注重对关键业务数据进行及时的保护,因为关键业务数据的丢失
可能会给企业带来不可估量的损失。

    SharePlex 为业务系统提供灾难恢复能力,容灾系统中的硬件环境又可用来降低系统维护工作
中的停机时间。这并不与企业的容灾方案相矛盾,因为事务可被发送到系统中的远程节点上。

    SharePlex 支持多种配置方案,包括对等配置方案,在这种配置方案中,两个数据库都处于可
用状态,因而可实现快速的失败接管。在容灾发方案中没有比这种失败接管更快的方法了。

    减少有计划的停机时间

    有计划的停机也可能对企业的服务水平、客户满意程度甚至股价等带来影响,而据估计企业
80%的停机是有计划的行为。

    利用 SharePlex,企业可几乎完全消除系统的停机时间而不用考虑在此期间进行何种维护工

http://emag.csdn.net       - 46 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》
作、哪个操作系统会受到影响,甚至不用考虑数据库版本的问题及对硬件环境进行何种操作。

    负载平衡

    SharePlex 可以将源系统的数据实时复制到目标系统,从而建立一个可以被访问的即席查询和
报表系统。目标系统可以是源系统的全集和子集。通过将查询和报表系统放在不同的数据库实例
中运行,可以平衡服务器负载并提高 OLTP 类生产系统的性能。一方面,可以减少 OLTP 应用和查
询报表应用之间的磁盘 I/O 冲突,提高 OLTP 应用的效率。另一方面,SharePlex 支持不同模式间
的复制。可以分别面向 OLTP 和查询系统的使用特点来进行设计,如建立索引,设置数据库表的参
数等等。

    在这种配置环境下,SharePlex 在线事务处理可以获得很好的性能,而决策支持和报表处理可
在不影响正常业务的情况下进行。

    当一种单一的数据复制模式不能满足企业的业务扩展需求和系统性能时,很容易利用
SharePlex 建立另外的复制模式,从而进一步扩展系统和提高报表处理的性能。

    系统移植

    尽管企业从规划设计良好的业务系统中收益,但也不得不面临系统移植和升级这一挑战。数
据集中、技术的推陈出新和服务器的移植都是导致必须进行系统移植的原因之一。

    SharePlex 可确保在进行以上工作时正常的事务处理得以继续进行。源系统的功能不受到任何
影响,SharePlex 只捕捉移植过程中发生变化的事务并将它们排队保存。当移植工作结束后,这些
被保存的事务将被应用到新系统中并进行数据同步工作。一旦数据同步后,用户活动会有非常短
暂的停顿,在此瞬间将完成系统的切换动作。

    数据集中和广播

    SharePlex 通过非常有效的管理控制机制来实现数据集中和广播。SharePlex 提供细化的数据筛
选功能,可按业务需要定制需要传输的数据,从而缓解和消除了数据传输过程中的安全和带宽问
题。例如,如果远程节点只需要有关本地员工的基本信息而无需薪水信息,那么只需利用 SharePlex
传输相关的数据行和字段即可。

    支持数据仓库应用、实现更好的决策支持

越来越多的公司在建设决策支持系统。传统的数据抽取、转换和装载工具按照时间段处理数据而

不能进行实时的数据处理,因而决策支持系统就不能真正体现出太大的价值。SharePlex 可以实时

捕捉、转换数据到决策支持系统中。



1.4. 容灾系统建立



http://emag.csdn.net       - 47 -        2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.4.1. 容灾系统状态定义

    为方便论述,本节模拟地点 A 和 B,两地各有一套运行在 Oracle 上的应用系统。通过 SharePlex
for Oracle 建立数据复制,以 B 地点的系统作为 A 地点的备份。

        正常情况下:

               业务系统运行在地点 A,包括数据库实例、有关的文件、数据库数据、应用软件。

               A 节点对外提供服务。

               A 节点所有的有关的数据通过 SharePlex for Oracle 实时复制到 B 节点。

        灾难发生的情况下,整个 A 地点无法正常提供服务:

               A 地点的业务将在 B 地点正常提供服务。当灾难发生时,主中心的数据库服务、

               应用软件切换到灾备中心的灾备节点。灾备节点对外提供服务。

               数据复制暂停。

               对主中心的数据库和应用系统进行恢复。

         计划内维护操作

               当进行计划内的维护时,主中心的数据库服务、应用软件切换到灾备中心的灾备
               节点。灾备节点对外提供服务。

               SharePlex for Oracle 记录进行维护期间数据的变化,存储到灾备节点的队列。

               当计划内的维护操作时完成时,将维护过程中的数据复制到 A 地点,将应用切换

               到 A 地点系统。



1.4.2. 容灾系统的的配置过程

1.4.2.1. 初始化高可用及容灾环境

    使用 SharePlex for Oracle 进行数据复制的前提是在主中心和灾备中心具有相同的数据。根据
用户对停机时间的要求、容灾环境和数据量的大小。可以采用 Oracle 自身提供的方法进行初始化
同步,包括:Oracle Cold Backup,Oracle Hot Backup,Export/import,Transprant tablespace 等等。

    为了保证初始化同步过程中源系统的可用性,SharePlex 提供 Reconcile 功能,当使用 Oracle

Hot backup 机制进行初始化同步时,通过 SharePlex 队列记录数据的变化。并在进行 post 的过程中

确认哪些数据通过 Recovery 进行恢复,把没有恢复的数据装载到数据库中。从而保证初始化同步

过程中源系统没有停机时间。

http://emag.csdn.net                   - 48 -              2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.4.2.2. 配置 Shareplex 的 Fail-over ready 状态

    为保证灾难发生时快速进行应用接管,需要配置 Fail-over ready 状态。

         确保源系统和目标系统 SharePlex for Oracle 启动。

         源系统中建立配置文件,目标系统建立反向配置文件。两个配置文件都处于激活状态。

         在 Secondary 端保证没有对复制表的 DML 操作;

         在 Secondary 端停止 export 进程,防止意外的数据操作改变源系统的数据。

         运行脚本取消 secondary 系统用户(除了 splex)的 insert,update 和 delete 权限;

         禁止 Secondary 中使用 trigger,cascade delete constraints,foreign-key constraints,check
         constrants,schedule jobs 等等。

         定期备份 Shareplex 相关的文件,文件包括

               Shareplex 的工作目录

               /var/adm/.splex/Shareplex.mark

               oratab file

               /etc/services

               /etc/system

               /etc/group

               操作系统 Shareplex 用户(默认为 Oracle 用户)的.profile 文件



1.4.2.3. 灾难发生时应用切换到灾备中心

    灾难发生时的接管工作由以下步骤组成:

         确认 Secondary 系统的 export 进程处于停止状态;

         确保在队列中的所有数据复制到 Secondary 系统中。用 qstatus 命令查看 Secondary 系统
         中的 post 进程,直到 backlog messages 一项为 0;

         在 Secondary 系统上运行 SQL 脚本给用户赋权,包括 insert, update 和 delete;

         在 Secondary 系统上运行 SQL 脚本 enable triggers 和 contraints;

         切换应用系统到 Secondary 系统;

         确保 Secondary 系统上的 Shareplex export 进程处于停止状态。

    切换过程所需要的时间主要是上述 6 个步骤所需要的时间的总和。正常情况下能够充分满足

30 分钟以内的切换要求。
http://emag.csdn.net                            - 49 -           2005 年 5 月 4 期 总第 4 期
《CSDN 社区电子杂志——Oracle 杂志》

1.4.2.4. 容灾中心的数据恢复到主中心

    从容灾中心的数据恢复到主中心的过程分为如下阶段:

         阶段 1:在 Primary System 中恢复复制环境。

         阶段 2:Purge 队列, 在 Primary System 中 Purge Capture,Export 和 Post 队列。因为
         Primary System 的复制环境是通过备份的软件进行恢复的。队列的内容已经过期。 在
         Secondary System 中 Purge Post 队列。原则上 Capture 和 Export 队列没有内容,而在 Post
         队列中需要清除没有被提交的部分数据。

         阶段 3:开始从 Secondary system 复制到 Primary System,保证 Primary System 的数据存
         储在 Post 队列中,但不加载到数据库中。

         阶段 4:同步数据,即在 Primary System 中重新建立新的数据库拷贝。

         阶段 5:在 Primary System 中进行 Activate。

         阶段 6:恢复 Object Cache。

         阶段 7:将用户切换到 Primary System。

    系统的恢复时间由上述的 7 个阶段构成,其中阶段 4 的时间较长,根据系统的数据量、目标

系统硬件选型不同,正常切换时间在 10-38 个小时之间。



1.4.2.5. 计划内系统维护

    计划内的 Shareplex failover 接管

         在 Primary 系统上停止用户对数据对象的访问;

         在 Primary 系统,运行 flush 命令,此命令停机目标机器上的 post 进程,并将队列中的
         内容装载到数据库中。

         关闭 Primary 中的 SharePlex 和 Oracle 数据库。

         运行脚本为 Secondary 系统的 oracle 用户赋 insert, update 和 delete 的权限;

         运行脚本激活 Secondary 系统的 oracle trigger 和 contraints;

         按照相应步骤重新部署用户和应用到 Secondary 系统;

         切换用户到 Secondary 系统,但不要启动 export 进程;

    计划内的 Shareplex failback 接管

         打开 Primary 系统的 Oracle 数据库; Primary 系统上对 Triggers、
                                   在                      Foreign-key constraints、
         Cascading delete constriants、Check constraints、Scheduled jobs that perform DML 进行修

http://emag.csdn.net                       - 50 -                2005 年 5 月 4 期 总第 4 期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期
Csdn Emag(Oracle)第四期

Contenu connexe

Tendances

Csdn Java电子杂志第2期
Csdn Java电子杂志第2期Csdn Java电子杂志第2期
Csdn Java电子杂志第2期yiditushe
 
Mongo db实战
Mongo db实战Mongo db实战
Mongo db实战Roger Xia
 
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wangOrclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wangmaclean liu
 
I Batis Sql Maps 2 Cn
I Batis Sql Maps 2 CnI Batis Sql Maps 2 Cn
I Batis Sql Maps 2 Cnzhuxuezheng
 
Jira用户使用指南 简化版
Jira用户使用指南 简化版Jira用户使用指南 简化版
Jira用户使用指南 简化版xu_jinyang
 
Viewing Android Source Files in Eclipse (Chinese)
Viewing Android Source Files in Eclipse  (Chinese)Viewing Android Source Files in Eclipse  (Chinese)
Viewing Android Source Files in Eclipse (Chinese)William Lee
 
电子杂志第六期
电子杂志第六期电子杂志第六期
电子杂志第六期yiditushe
 
深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)colderboy17
 
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.033120160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331liu sheng
 
51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册poker mr
 
Pl sql developer7.0用户指南
Pl sql developer7.0用户指南Pl sql developer7.0用户指南
Pl sql developer7.0用户指南irons_zhou
 

Tendances (13)

Csdn Java电子杂志第2期
Csdn Java电子杂志第2期Csdn Java电子杂志第2期
Csdn Java电子杂志第2期
 
Mongo db实战
Mongo db实战Mongo db实战
Mongo db实战
 
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wangOrclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
Orclrecove 1 pd-prm-dul testing for oracle database recovery_20141030_biot_wang
 
I Batis Sql Maps 2 Cn
I Batis Sql Maps 2 CnI Batis Sql Maps 2 Cn
I Batis Sql Maps 2 Cn
 
Jira用户使用指南 简化版
Jira用户使用指南 简化版Jira用户使用指南 简化版
Jira用户使用指南 简化版
 
Viewing Android Source Files in Eclipse (Chinese)
Viewing Android Source Files in Eclipse  (Chinese)Viewing Android Source Files in Eclipse  (Chinese)
Viewing Android Source Files in Eclipse (Chinese)
 
电子杂志第六期
电子杂志第六期电子杂志第六期
电子杂志第六期
 
深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)深入浅出My sql数据库开发、优化与管理维护 (1)
深入浅出My sql数据库开发、优化与管理维护 (1)
 
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.033120160315内刊投稿(刘胜)区块链研究综述v1.1.0331
20160315内刊投稿(刘胜)区块链研究综述v1.1.0331
 
51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册51 cto下载 2010-ccna实验手册
51 cto下载 2010-ccna实验手册
 
Direct show
Direct showDirect show
Direct show
 
Hai00021404
Hai00021404Hai00021404
Hai00021404
 
Pl sql developer7.0用户指南
Pl sql developer7.0用户指南Pl sql developer7.0用户指南
Pl sql developer7.0用户指南
 

En vedette

上海立派信息技术有限公司
上海立派信息技术有限公司上海立派信息技术有限公司
上海立派信息技术有限公司yiditushe
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析yiditushe
 
Jsp面试知识
Jsp面试知识Jsp面试知识
Jsp面试知识yiditushe
 
Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象yiditushe
 
Ebay架构演变历程
Ebay架构演变历程Ebay架构演变历程
Ebay架构演变历程yiditushe
 
J2 Ee服务器端高级编程
J2 Ee服务器端高级编程J2 Ee服务器端高级编程
J2 Ee服务器端高级编程yiditushe
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题yiditushe
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Luceneyiditushe
 
Ruby语言入门教程
Ruby语言入门教程Ruby语言入门教程
Ruby语言入门教程yiditushe
 
Java面试题集
Java面试题集Java面试题集
Java面试题集yiditushe
 

En vedette (10)

上海立派信息技术有限公司
上海立派信息技术有限公司上海立派信息技术有限公司
上海立派信息技术有限公司
 
Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析Lucene 3[1] 0 原理与代码分析
Lucene 3[1] 0 原理与代码分析
 
Jsp面试知识
Jsp面试知识Jsp面试知识
Jsp面试知识
 
Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象Jdbc中操作Blob、Clob等对象
Jdbc中操作Blob、Clob等对象
 
Ebay架构演变历程
Ebay架构演变历程Ebay架构演变历程
Ebay架构演变历程
 
J2 Ee服务器端高级编程
J2 Ee服务器端高级编程J2 Ee服务器端高级编程
J2 Ee服务器端高级编程
 
2006年招聘试题
2006年招聘试题2006年招聘试题
2006年招聘试题
 
开放源代码的全文检索Lucene
开放源代码的全文检索Lucene开放源代码的全文检索Lucene
开放源代码的全文检索Lucene
 
Ruby语言入门教程
Ruby语言入门教程Ruby语言入门教程
Ruby语言入门教程
 
Java面试题集
Java面试题集Java面试题集
Java面试题集
 

Similaire à Csdn Emag(Oracle)第四期

Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期yiditushe
 
My Eclipse 6 Java Ee开发中文手册
My Eclipse 6 Java Ee开发中文手册My Eclipse 6 Java Ee开发中文手册
My Eclipse 6 Java Ee开发中文手册yiditushe
 
一次Web性能测试小结
一次Web性能测试小结一次Web性能测试小结
一次Web性能测试小结beiyu95
 
Cite space中文手册
Cite space中文手册Cite space中文手册
Cite space中文手册cueb
 
Java explore
Java exploreJava explore
Java exploreRoger Xia
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程yiditushe
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程appollo0312
 
How to-become-ocm1
How to-become-ocm1How to-become-ocm1
How to-become-ocm1xiaoshi100a
 
深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护colderboy17
 
CloudTao技术白皮书
CloudTao技术白皮书CloudTao技术白皮书
CloudTao技术白皮书FIT2CLOUD
 
Memcached
MemcachedMemcached
Memcachednowise
 
Memcached全面剖析
Memcached全面剖析Memcached全面剖析
Memcached全面剖析chen vivian
 
Memcached
MemcachedMemcached
Memcachedfeizone
 
Linux 期末報告
Linux 期末報告Linux 期末報告
Linux 期末報告米米 林
 
Web性能测试指标参考v0.2
Web性能测试指标参考v0.2Web性能测试指标参考v0.2
Web性能测试指标参考v0.2beiyu95
 
+++º+ ¦¦ ¦ ¦¦ ¦+ =
+++º+ ¦¦  ¦ ¦¦ ¦+ =+++º+ ¦¦  ¦ ¦¦ ¦+ =
+++º+ ¦¦ ¦ ¦¦ ¦+ =guesta6295f3
 
Dwr中文文档
Dwr中文文档Dwr中文文档
Dwr中文文档yiditushe
 

Similaire à Csdn Emag(Oracle)第四期 (20)

Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期Csdn Emag(Oracle)第三期
Csdn Emag(Oracle)第三期
 
My Eclipse 6 Java Ee开发中文手册
My Eclipse 6 Java Ee开发中文手册My Eclipse 6 Java Ee开发中文手册
My Eclipse 6 Java Ee开发中文手册
 
一次Web性能测试小结
一次Web性能测试小结一次Web性能测试小结
一次Web性能测试小结
 
Cite space中文手册
Cite space中文手册Cite space中文手册
Cite space中文手册
 
Java explore
Java exploreJava explore
Java explore
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程Struts+Spring+Hibernate整合教程
Struts+Spring+Hibernate整合教程
 
xcvx
xcvxxcvx
xcvx
 
How to-become-ocm1
How to-become-ocm1How to-become-ocm1
How to-become-ocm1
 
深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护深入浅出My sql数据库开发、优化与管理维护
深入浅出My sql数据库开发、优化与管理维护
 
CloudTao技术白皮书
CloudTao技术白皮书CloudTao技术白皮书
CloudTao技术白皮书
 
Memcached
MemcachedMemcached
Memcached
 
Memcached
MemcachedMemcached
Memcached
 
Memcached全面剖析
Memcached全面剖析Memcached全面剖析
Memcached全面剖析
 
Memcached
MemcachedMemcached
Memcached
 
Linux 期末報告
Linux 期末報告Linux 期末報告
Linux 期末報告
 
Abaqus
AbaqusAbaqus
Abaqus
 
Web性能测试指标参考v0.2
Web性能测试指标参考v0.2Web性能测试指标参考v0.2
Web性能测试指标参考v0.2
 
+++º+ ¦¦ ¦ ¦¦ ¦+ =
+++º+ ¦¦  ¦ ¦¦ ¦+ =+++º+ ¦¦  ¦ ¦¦ ¦+ =
+++º+ ¦¦ ¦ ¦¦ ¦+ =
 
Dwr中文文档
Dwr中文文档Dwr中文文档
Dwr中文文档
 

Plus de yiditushe

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要yiditushe
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册yiditushe
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2yiditushe
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1yiditushe
 
性能测试技术
性能测试技术性能测试技术
性能测试技术yiditushe
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术yiditushe
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试yiditushe
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训yiditushe
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程yiditushe
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍yiditushe
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Actionyiditushe
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1yiditushe
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demoyiditushe
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践yiditushe
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则yiditushe
 
10 团队开发
10  团队开发10  团队开发
10 团队开发yiditushe
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模yiditushe
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模yiditushe
 
6 架构设计
6  架构设计6  架构设计
6 架构设计yiditushe
 
5 架构分析
5  架构分析5  架构分析
5 架构分析yiditushe
 

Plus de yiditushe (20)

Spring入门纲要
Spring入门纲要Spring入门纲要
Spring入门纲要
 
J Bpm4 1中文用户手册
J Bpm4 1中文用户手册J Bpm4 1中文用户手册
J Bpm4 1中文用户手册
 
性能测试实践2
性能测试实践2性能测试实践2
性能测试实践2
 
性能测试实践1
性能测试实践1性能测试实践1
性能测试实践1
 
性能测试技术
性能测试技术性能测试技术
性能测试技术
 
Load runner测试技术
Load runner测试技术Load runner测试技术
Load runner测试技术
 
J2 ee性能测试
J2 ee性能测试J2 ee性能测试
J2 ee性能测试
 
面向对象的Js培训
面向对象的Js培训面向对象的Js培训
面向对象的Js培训
 
Flex3中文教程
Flex3中文教程Flex3中文教程
Flex3中文教程
 
基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍基于分词索引的全文检索技术介绍
基于分词索引的全文检索技术介绍
 
Lucene In Action
Lucene In ActionLucene In Action
Lucene In Action
 
Lucene2 4学习笔记1
Lucene2 4学习笔记1Lucene2 4学习笔记1
Lucene2 4学习笔记1
 
Lucene2 4 Demo
Lucene2 4 DemoLucene2 4 Demo
Lucene2 4 Demo
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
7 面向对象设计原则
7 面向对象设计原则7 面向对象设计原则
7 面向对象设计原则
 
10 团队开发
10  团队开发10  团队开发
10 团队开发
 
9 对象持久化与数据建模
9  对象持久化与数据建模9  对象持久化与数据建模
9 对象持久化与数据建模
 
8 Uml构架建模
8  Uml构架建模8  Uml构架建模
8 Uml构架建模
 
6 架构设计
6  架构设计6  架构设计
6 架构设计
 
5 架构分析
5  架构分析5  架构分析
5 架构分析
 

Csdn Emag(Oracle)第四期

  • 2. 《CSDN 社区电子杂志——Oracle 杂志》 目录 目录 ........................................................................................................................................................- 2 - 数据库实战 ..........................................................................................................................................- 4 - 利用errorstack event解决问题 .............................................................................................................- 4 - 数据库开发 ..........................................................................................................................................- 8 - Oracle外部例程......................................................................................................................................- 8 - 1.1. 必要性 .................................................................................................................................- 8 - 1.2. 基本原理 .............................................................................................................................- 9 - 1.3. 使用配置 .............................................................................................................................- 9 - 1.4. 使用COM对象说明 .......................................................................................................... - 11 - 1.5. 操作Excel示例 ..................................................................................................................- 13 - 1.6. 小结 ...................................................................................................................................- 21 - 数据库复制 ........................................................................................................................................- 23 - 最简单的创建只读实体化视图站点的方法 .......................................................................................- 23 - 1.1. 主站点上创建实体化视图日志表....................................................................................- 23 - 1.2. 实体化视图站点上创建公用数据库链接........................................................................- 23 - 1.3. 实体化视图站点上创建刷新组,本例中 3 分钟刷新一次............................................- 23 - 1.4. 实体化视图站点上创建用户私有数据库链接................................................................- 24 - 1.5. 实体化视图站点上创建实体化视图................................................................................- 24 - 1.6. 实体化视图站点上将创建的视图加入刷新组................................................................- 24 - 1.7. 测试 ...................................................................................................................................- 24 - 1.8. 总结 ...................................................................................................................................- 24 - 1.9. 附录 ...................................................................................................................................- 25 - Oracle高级复制冲突解决机制的研究................................................................................................- 27 - 数据库高可用性 ...............................................................................................................................- 37 - SharePlex for Oracle ...........................................................................................................................- 37 - 1.1. 前言 ...................................................................................................................................- 37 - 1.2. 高可用容灾方案设计 .......................................................................................................- 37 - http://emag.csdn.net -2- 2005 年 5 月 4 期 总第 4 期
  • 3. 《CSDN 社区电子杂志——Oracle 杂志》 1.3. SharePlex for Oracle介绍..................................................................................................- 42 - 1.4. 容灾系统建立 ...................................................................................................................- 47 - 1.5. 关于Quest Software...........................................................................................................- 53 - 1.6. SharePlex for Oracle部分成功案例 ..................................................................................- 53 - 博文精品图书连载...........................................................................................................................- 55 - 《Oracle JDeveloper 10g 与 J2EE实践演练》 ...............................................................................- 55 - 1.1. J2EE 应用程序模型简介 .................................................................................................- 55 - 1.2. Oracle 应用程序开发框架(ADF) ...............................................................................- 56 - 1.3. Oracle JDeveloper 10g 功能概览.....................................................................................- 58 - 1.4. 结语 ...................................................................................................................................- 67 - 1.5. 本书相关资源 ...................................................................................................................- 67 - 关于CSDN..........................................................................................................................................- 69 - http://emag.csdn.net -3- 2005 年 5 月 4 期 总第 4 期
  • 4. 《CSDN 社区电子杂志——Oracle 杂志》 数据库实战 利用 errorstack event 解决问题 本文作者: Kamus (kamusis@gmail.com ) 摘要:在任何一种解决问题之前,必须要先知道问题的原因,才可以作到有的放矢。解决问 题的方法并不是很难找,难能可贵的是能够及时准确地定位问题。本文介绍一种利用 trace event 来定位问题所在的方法。 某天现场人员报告说 exp 的时候报权限不足的错误。 是用当前用户作的用户级别的 exp,按理说应该没有什么权限的问题。 按照现场的情况作了测试,果然重现了问题。 d:Temp>exp parfile=exp.par Export: Release 9.2.0.5.0 - Production on Tue Dec 21 22:27:13 2004 Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved. EXP-00008: ORACLE error 1031 encountered ORA-01031: insufficient privileges EXP-00000: Export terminated unsuccessfully 其中 exp.par 的内容如下: userid=scott/tiger file=.scott.dmp indexes=y grants=y rows=y constraints=y owner=scott direct=n http://emag.csdn.net -4- 2005 年 5 月 4 期 总第 4 期
  • 5. 《CSDN 社区电子杂志——Oracle 杂志》 compress=n feedback=10000 resumable=y resumable_timeout=7200 log=.export.log 没有发现什么问题,那么作一个 trace 吧,于是决定使用 errorstack event,由于 exp 是在命令行中 直接执行的,所以只能对整个数据库系统作 trace,由于只是想知道 ORA-01031 错误的发生原因, 所以用以下语句: alter system set events '1031 trace name errorstack level 3'; 如果想捕获什么错误,就直接用错误号作 trace,此处我们想获知 ORA-01031 的错误原因, 所以使用了’1031 trace name errorstack level 3’。 然后重新运行 exp,仍然报错,这时候在 udump 目录中生成了 trace 文件,检查文件内容,发现: *** SESSION ID:(15.210) 2004-12-21 22:22:36.704 *** 2004-12-21 22:22:36.704 ksedmp: internal or fatal error ORA-01031: insufficient privileges Current SQL statement for this session: ALTER SESSION ENABLE RESUMABLE TIMEOUT 7200 原来问题出在 ENABLE RESUMABLE 部分,这是 9i 的新特性,用于在出现空间不足的问题时, 挂起整个操作以等待操作人员解决空间问题。 只要确认了问题所在,就很好解决了,其实如果详细地看过 adminitrator 文档,也就不会犯这个错 误,文档里面 Enabling and Disabling Resumable Space Allocation 部分很清楚地写着:如果要使用 resumbale 特性,那么必须有 resumable 系统权限。 检查现场用户的权限,发现只有 connect 和 resource 权限。于是: grant resumable to username; 当然如果象一些应用里面那样,用户始终是具有 DBA 角色的话,那么永远也不会发生这个错误, 因为 DBA 角色本来就具有 esumable 系统权限。不过为了安全起见,我们的应用中用户都不会具有 http://emag.csdn.net -5- 2005 年 5 月 4 期 总第 4 期
  • 6. 《CSDN 社区电子杂志——Oracle 杂志》 DBA 权限。 解决问题的方法很简单,没什么好说的,本文想介绍的也是发现问题的手段,也就是利用 set events 的方法。这个方法在我们对一个错误感到莫名其妙的时候往往会成为指路明 灯。 作为本文的补充,提供几个常见的用于 Troubleshooting 或者 Tuning 或者 Interal 研究的 Oracle Events。 10032 事件:用于 dump 排序操作的统计值,Level 10 是最详细的级别。 ALTER SESSION SET EVENTS '10032 trace name context forever, level 10'; 10046 事件:用于跟踪 SQL 执行过程,这是我们在调整一个 SQL 时比较常见的方法。Level 12 是最详细的级别。 ALTER SESSION SET EVENTS '10046 trace name context forever, level 12'; 其中各个 Level 的含义: 1:显示 SQL 语句,执行计划和执行统计值 4:显示级别 1 的内容和绑定变量 8:显示级别 1 的那同和等待事件统计 12:显示级别 1 的内容和绑定变量、等待事件统计 10053 事件:当 Oracle 使用 CBO 进行执行计划的生成时,可以使用这个事件对于执行计划的生 成过程进行跟踪。 ALTER SESSION SET EVENTS '10053 trace name context forever, level 1'; 10081 事件:用于跟踪 HWM(高水位标志)的变更 ALTER SESSION SET EVENTS '10081 trace name context forever, level 1'; http://emag.csdn.net -6- 2005 年 5 月 4 期 总第 4 期
  • 7. 《CSDN 社区电子杂志——Oracle 杂志》 作者简介: 张乐奕,网名 kamus 曾任 ITPUB Oracle 认证版版主,现任 itpub Oracle 管理版版主。 现任职于北京某大型软件公司,首席DBA,主要负责证券行业的全国十数处核心交易系统数据库管 理及维护工作。 热切关注Oracle技术和其它相关技术,出没于各大数据库技术论坛,目前是中国最大的Oracle技 术论坛www.itpub.net的数据库管理版版主。 阅读更多技术文章和随笔可以登录我的个人blog。 http://blog.dbform.com。 http://emag.csdn.net -7- 2005 年 5 月 4 期 总第 4 期
  • 8. 《CSDN 社区电子杂志——Oracle 杂志》 数据库开发 Oracle 外部例程 —— PL/SQL 操作 COM 对象 本文作者: chanet (chanet@oracle.com.cn ) PL/SQL 是由 Oracle 公司对标准 SQL 进行扩展,专用于 Oracle 数据库中程序设计的专用语言, 属第三代过程式程序设计语言。从 Oracle8 开始提供了直接从 PL/SQL 中调用外部 C 语言过程,允 许开发人员用 PL/SQL 进行使用 C 语言编制的程序模块。从 Oracle8i 开始,又引入了 Java 程序。 在本文中主要介绍外部例程的基本原理以及使用条件,介绍如何通过引用外部例程来操作 Windows 中的 COM 对象,并做了一个操作 Excel 对象的示例。 本 文 的 运 行 环 境 全 部 建 立 在 Oracle9i 和 Windows2000 。 其 中 ORACLE 的 安 装 目 录 (ORACLE_HOME)为 D:oracleora92,SID 为 ORADB,主机名为 CHANET。 1.1. 必要性 扩展后的 PL/SQL 语言已经集成了标准 SQL,在效率和安全上非常适合设计 Oracle 数据库程 序,但对于应用的某些功能,其它的程序设计语言比 PL/SQL 更适合,如:使用操作系统资源,C 语言在计算和引用系统对象及使用设备上优于 PL/SQL, Java 语言在网络上的应用优于 PL/SQL。 而 如果在应用上要用到不适合用 PL/SQL 语言的话,这时就要使用其它语言进行编制,然后由 PL/SQL 作为外部例程进行调用。 在 Oracle8 之 前 的 版 本 , PL/SQL 和 其 它 语 言 的 唯 一 通 信 是 借 助 于 DBMS_PIPE 和 DBMS_ALERT 包来实现,在使用之前必需建立一个 OCI 接口或预编译器编制的监护程序,使用 比较复杂。外部例程的出现,只需在 PL/SQL 中建立一个函数映射到外部例程对应的函数,就像普 通的 PL/SQL 函数使用一样,简化了使用过程。 http://emag.csdn.net -8- 2005 年 5 月 4 期 总第 4 期
  • 9. 《CSDN 社区电子杂志——Oracle 杂志》 1.2. 基本原理 当引用外部 C 语言例程时,Oracle 监听器将启动 extproc 进程,该进程将会动态地载入共享库 (在 Windows 下称为动态链接库,即是 DLL 文件),进程起了一个缓冲的作用,当 PL/SQL 过程 调用外部函数时,进程把命令发送到共享库,之后把结果返回给 PL/SQL 过程。 进程被调用后随着共享库的使用会话(session)而存在,如果调用完毕或者关闭数据库用户会话, extproc 进程会自动关闭。 如下图 1-1 为调用外部例程的描述。 图 1-1 监听器与 extproc 进程 1.3. 使用配置 在调用外部例程之前,必需进行如下设置: 配置监听器。 配置 Net 组件服务。 配置监听器,打开 D:oracleora92networkadminlistener.ora 文件,修改文件参数。 LISTENER = (DESCRIPTION_LIST = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = TCP)(HOST = CHANET)(PORT = 1521)) ) (ADDRESS_LIST = http://emag.csdn.net -9- 2005 年 5 月 4 期 总第 4 期
  • 10. 《CSDN 社区电子杂志——Oracle 杂志》 (ADDRESS = (PROTOCOL = IPC)(KEY = extproc1)) ) ) ) SID_LIST_LISTENER = (SID_LIST = (SID_DESC = (SID_NAME = PLSExtProc) (ORACLE_HOME = D:oracleora92) (PROGRAM = extproc) ) (SID_DESC = (GLOBAL_DBNAME = ORADB) (ORACLE_HOME = D:oracleora92) (SID_NAME = ORADB) ) ) 其中有两部份参数对于使用外部例程是很重要的。 (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = extproc1)) 设置基于 IPC 协议的外部例程 (SID_DESC =(SID_NAME = PLSExtProc) (ORACLE_HOME = D:oracleora92) (PROGRAM = extproc) ) 记录数据库的相关属性,SID_NAME 在默认的情况下是 PLSExtproc。 配置 Net 组件服务,打开 D:oracleora92networkadmintnsnames.ora 文件,把如下内容保存在 该文件里。 EXTPROC_CONNECTION_DATA = (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1)) ) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) ) ) 重要参数说明: (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC1)) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO) 两设置必需与 listener.ora 里的一致。 重启监听器,并测试服务是否可用。 http://emag.csdn.net - 10 - 2005 年 5 月 4 期 总第 4 期
  • 11. 《CSDN 社区电子杂志——Oracle 杂志》 停止监听器:lsnrctl stop 启动监听器:lsnrctl start 测试服务是否可用: C:>tnsping EXTPROC_CONNECTION_DATA TNS Ping Utility for 32-bit Windows: Version 9.2.0.1.0 - Production on 07-4 月 -2 005 16:57:00 Copyright (c) 1997 Oracle Corporation. All rights reserved. 已使用的参数文件: D:oracleora92networkadminsqlnet.ora 已使用 TNSNAMES 适配器来解析别名 Attempting to contact (DESCRIPTION = (ADDRESS_LIST = (ADDRESS = (PROTOCOL = IPC) (KEY = EXTPROC1))) (CONNECT_DATA = (SID = PLSExtProc) (PRESENTATION = RO))) OK(30 毫秒) 测试 extproc 进程是否正常: D:oracleora92bin>extproc Oracle Corporation --- 星期四 4 月 07 2005 17:37:18.968 Heterogeneous Agent Release 9.2.0.1.0 - Production 1.4. 使用 COM 对象说明 COM 对象设计都会提供了三个基本操作给开发人员使用,分别为:获取属性值,设置属性值 (只读属性除外),调用方法。Oracle 数据库在 Windows 的平台下提供了操作 COM 对象的接口, 属于 C 语言外部例程模式。 工作原理如下图: http://emag.csdn.net - 11 - 2005 年 5 月 4 期 总第 4 期
  • 12. 《CSDN 社区电子杂志——Oracle 杂志》 图 1-2 操作 COM 对象工作原理 在使用该功能之前,需明白如下内容: 1、创建 COM 对象操作函数。 SQL> CONNECT SYSTEM/chanet@oradb SQL> CREATE USER chanet identified by chanet; SQL> GRANT CREATE LIBRARY TO chanet; SQL> CONNECT chanet/chanet@oradb; SQL> @D:oracleora92comcomwrap.sql; 2、配置监听器。 在 listener.ora 文件里,添加如下内容,并重启监听器。 STARTUP_WAIT_TIME_LISTENER = 0 CONNECT_TIMEOUT_LISTENER = 10 TRACE_LEVEL_LISTENER = off PASSWORDS_LINTENER = (oracle) 3、PL/SQL 数据类型与对应的 COM 对象类型。 表 1-1 数据类型比较 PL/SQL 数据类型 COM API 数据类型 VARCHAR2 BSTR BOOLEAN BOOL BINARY_INTEGER BYTE,INT,LONG DOUBLE PRECISION DOUBLE,FLOAT,CURRENCY DATE DATE 4、函数说明。 表 1-2 函数说明 名称 功能描述 CreateObject 创建对象 DestroyObject 关闭对象 GetLastError 获取错误信息 http://emag.csdn.net - 12 - 2005 年 5 月 4 期 总第 4 期
  • 13. 《CSDN 社区电子杂志——Oracle 杂志》 GetProperty 获取属性值 SetProperty 设置属性值 InitArg 为 Invoke 函数初始化参数 InitOutArg 为 GetArg 初始化输出参数 GetArg 获取输出参数 SetArg 为 Invoke 函数设置参数 Invoke 调用 COM 对象的函数或过程 1.5. 操作 Excel 示例 本节介绍如何操作 COM 对象(以 Excel 对象为例) 将数据库里的表记录通过 PL/SQL 语句输 , 出成 Excel 文件。通过对象浏览器可以查看 Excel 对象提供的属性和方法。 (如:在 Excel 菜单,工 具 -> 宏 -> 打开 Visual Basic 编辑器,在编辑器里,视图 -> 对象浏览器)。 使用 Excel 对象一般针对单元格进行操作(如,设置第一个单元格字体大小的代码为: Range("A1").Font.Size = 20)。对应的 COM 外部例程操作的步骤为:1、获取程序句柄;2、获取工 作簿句柄;3、获取工作表句柄;4、获取 Range 区句柄;5、获取 Font 类句柄;6、设置 Size 属性。 如下为操作 Excel 对象的例子,首先建立示例表,然后建立操作包(package),最后是使用包 函数的过程(procedure) 。创建一个测试用表: -- 销售表(脚本) CREATE TABLE IT_SALE_TAB(ITS_ID VARCHAR2(5),ITS_DATE DATE,ITS_TOTAL NUMBER); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('1',TO_DATE('2004-01-01','YYYY-MM-DD'),250); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('2',TO_DATE('2004-02-01','YYYY-MM-DD'),150); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('3',TO_DATE('2004-03-01','YYYY-MM-DD'),80); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('4',TO_DATE('2004-04-01','YYYY-MM-DD'),96); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('5',TO_DATE('2004-05-01','YYYY-MM-DD'),300); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('6',TO_DATE('2004-06-01','YYYY-MM-DD'),210); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('7',TO_DATE('2004-07-01','YYYY-MM-DD'),320); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('8',TO_DATE('2004-08-01','YYYY-MM-DD'),280); http://emag.csdn.net - 13 - 2005 年 5 月 4 期 总第 4 期
  • 14. 《CSDN 社区电子杂志——Oracle 杂志》 INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('9',TO_DATE('2004-09-01','YYYY-MM-DD'),276); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('10',TO_DATE('2004-10-01','YYYY-MM-DD'),368); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('11',TO_DATE('2004-11-01','YYYY-MM-DD'),163); INSERT INTO IT_SALE_TAB(ITS_ID,ITS_DATE,ITS_TOTAL) VALUES('12',TO_DATE('2004-12-01','YYYY-MM-DD'),305); COMMIT; 操作 Excel 对象包(Package)。 CREATE OR REPLACE PACKAGE oraExcel IS xlThin BINARY_INTEGER DEFAULT 2; DummyToken BINARY_INTEGER; applicationToken BINARY_INTEGER:=-1; -- Excel 对象句柄 WorkBooksToken BINARY_INTEGER:=-1; -- 工作簿句柄 WorkBookToken BINARY_INTEGER:=-1; WorkSheetToken BINARY_INTEGER:=-1; -- 工作表句柄 WorkSheetToken1 BINARY_INTEGER:=-1; RangeToken BINARY_INTEGER:=-1; -- Range 区句柄 ChartObjectToken BINARY_INTEGER:=-1; -- 图表对象句柄 ChartObject1 BINARY_INTEGER:=-1; Chart1Token BINARY_INTEGER:=-1; hLines BINARY_INTEGER:=-1; i BINARY_INTEGER; err_src VARCHAR2(255); err_desc VARCHAR2(255); err_hpf VARCHAR2(255); err_hpID BINARY_INTEGER; -- 创建 Excel 对象 FUNCTION CreateExcelWorkSheet(servername VARCHAR2) RETURN BINARY_INTEGER; -- 插入数据(字符型) FUNCTION setCellValues(RANGE VARCHAR2,data VARCHAR2,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 插入数据(日期型) FUNCTION setCellValues(RANGE VARCHAR2,data DATE,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 插入数据(整型) FUNCTION setCellValues(RANGE VARCHAR2,data BINARY_INTEGER,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 插入数据(实型) FUNCTION setCellValuesReal(RANGE VARCHAR2,data DOUBLE PRECISION,TYPE VARCHAR2) http://emag.csdn.net - 14 - 2005 年 5 月 4 期 总第 4 期
  • 15. 《CSDN 社区电子杂志——Oracle 杂志》 RETURN BINARY_INTEGER; -- 设置列宽 FUNCTION setCellColWidth(RANGE VARCHAR2,width DOUBLE PRECISION,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 设置表格 FUNCTION setCellLines(RANGE VARCHAR2,BordersIndex BINARY_INTEGER,weight BINARY_INTEGER DEFAULT xlThin,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 合并单元格 FUNCTION setCellMerge(RANGE VARCHAR2,bValues BOOLEAN,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 设置字体属性 FUNCTION setCellFont(RANGE VARCHAR2,Property VARCHAR2, fontValues BINARY_INTEGER,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 调用方法 FUNCTION callMethod(RANGE VARCHAR2,MethodName VARCHAR2) RETURN BINARY_INTEGER; -- 插入图表 FUNCTION InsertChart(xpos BINARY_INTEGER,ypos BINARY_INTEGER, width BINARY_INTEGER,height BINARY_INTEGER, RANGE VARCHAR2,TYPE VARCHAR2) RETURN BINARY_INTEGER; -- 保存文件 FUNCTION SaveToFile(filename VARCHAR2) RETURN BINARY_INTEGER; -- 关闭 Excel 对象 FUNCTION CloseExcel RETURN BINARY_INTEGER; END oraExcel; 数据包体内容(PACKAGE BODY) CREATE OR REPLACE PACKAGE BODY oraExcel IS FUNCTION CreateExcelWorkSheet(servername VARCHAR2) RETURN BINARY_INTEGER IS BEGIN -- 创建 Excel 对象 i:=ordcom.CreateObject('Excel.Application', 0, servername,applicationToken); IF (i!=0) THEN -- 创建失败,提示返回的错误信息 ordcom.GetLastError(err_src, err_desc, err_hpf, err_hpID); raise_application_error(-20000,err_src || err_desc || err_hpf || err_hpID); END IF; -- 通过程序对象句柄获取工作簿句柄 i:=ordcom.GetProperty(applicationToken, 'WorkBooks', 0, WorkBooksToken); ordcom.InitArg(); ordcom.SetArg(-4167,'I4'); i:=ordcom.Invoke(WorkBooksToken, 'Add', 1, WorkBookToken); ordcom.InitArg(); ordcom.SetArg('Sheet 1','BSTR'); http://emag.csdn.net - 15 - 2005 年 5 月 4 期 总第 4 期
  • 16. 《CSDN 社区电子杂志——Oracle 杂志》 -- 获取工作表句柄 i:=ordcom.GetProperty(applicationToken, 'WorkSheets', 0, WorkSheetToken1); i:=ordcom.Invoke(WorkSheetToken1, 'Add', 0, WorkSheetToken); RETURN i; END CreateExcelWorkSheet; FUNCTION setCellValues(RANGE VARCHAR2,data VARCHAR2, TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); -- 获取 Range 区句柄,之后将数据写入到指定的单元格 i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken); i:=ordcom.SetProperty(RangeToken, 'Value', data, TYPE); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellValues; FUNCTION setCellValues(RANGE VARCHAR2,data BINARY_INTEGER,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE, 'BSTR'); i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken); i:=ordcom.SetProperty(RangeToken, 'Value', data, type); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellValues; FUNCTION setCellValuesReal(RANGE VARCHAR2,data DOUBLE PRECISION,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE, 'BSTR'); i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken); i:=ordcom.SetProperty(RangeToken, 'Value', data, type); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellValuesReal; FUNCTION setCellValues(RANGE VARCHAR2,data DATE,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE, 'BSTR'); i:=ordcom.GetProperty(WorkSheetToken, 'Range', 1, RangeToken); i:=ordcom.SetProperty(RangeToken, 'Value', data, TYPE); i:=ordcom.DestroyObject(RangeToken); http://emag.csdn.net - 16 - 2005 年 5 月 4 期 总第 4 期
  • 17. 《CSDN 社区电子杂志——Oracle 杂志》 RETURN i; END setCellValues; FUNCTION setCellColWidth(RANGE VARCHAR2,width DOUBLE PRECISION,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken); i:=ordcom.SetProperty(RangeToken,'ColumnWidth',width,TYPE); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellColWidth; FUNCTION setCellMerge(RANGE VARCHAR2,bValues BOOLEAN,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken); i:=ordcom.SetProperty(RangeToken,'MergeCells',bValues,'BOOLEAN'); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellMerge; FUNCTION setCellLines(RANGE VARCHAR2,BordersIndex BINARY_INTEGER, weight BINARY_INTEGER DEFAULT xlThin,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken); ordcom.InitArg(); ordcom.SetArg(BordersIndex,TYPE); -- 画表格的具体载入参数 i:=ordcom.GetProperty(RangeToken,'Borders',1,hLines); i:=ordcom.SetProperty(hLines,'weight',weight,TYPE); i:=ordcom.DestroyObject(hLines); i:=ordcom.DestroyObject(RangeToken); RETURN i; END setCellLines; FUNCTION setCellFont(RANGE VARCHAR2,Property VARCHAR2,fontValues BINARY_INTEGER,TYPE VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken); ordcom.InitArg(); ordcom.SetArg(Property,TYPE); http://emag.csdn.net - 17 - 2005 年 5 月 4 期 总第 4 期
  • 18. 《CSDN 社区电子杂志——Oracle 杂志》 i:=ordcom.GetProperty(RangeToken,'Font',0,hLines); -- 获取字体对象 i:=ordcom.SetProperty(hLines,Property,fontValues,TYPE); i:=ordcom.DestroyObject(hLines); i:=ordcom.DestroyObject(RangeToken); RETURN i; END; FUNCTION callMethod(RANGE VARCHAR2,MethodName VARCHAR2) RETURN BINARY_INTEGER IS reti BINARY_INTEGER := -1; BEGIN ordcom.InitArg(); ordcom.SetArg(RANGE,'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range',1,RangeToken); ordcom.InitArg(); i:=ordcom.Invoke(RangeToken,MethodName,0,reti); -- 调用对象的方法 i:=ordcom.DestroyObject(RangeToken); RETURN reti; END; FUNCTION InsertChart(xpos BINARY_INTEGER, ypos BINARY_INTEGER, width BINARY_INTEGER, height BINARY_INTEGER, RANGE VARCHAR2, TYPE VARCHAR2) RETURN BINARY_INTEGER IS charttype BINARY_INTEGER:= -4099; BEGIN ordcom.InitArg(); i:=ordcom.GetProperty(WorkSheetToken, 'ChartObjects', 0, ChartObjectToken); ordcom.InitArg(); ordcom.SetArg(xpos,'I2'); -- 载入图表对象位置参数 ordcom.SetArg(ypos,'I2'); ordcom.SetArg(width,'I2'); ordcom.SetArg(height,'I2'); i:=ordcom.Invoke(ChartObjectToken, 'Add', 4, ChartObject1); -- 添加图表 i:=ordcom.GetProperty(ChartObject1, 'Chart', 0,Chart1Token); ordcom.InitArg(); ordcom.SetArg(RANGE, 'BSTR'); i:=ordcom.GetProperty(WorkSheetToken,'Range', 1, RangeToken); -- 选取区域 ordcom.InitArg(); ordcom.SetArg(RangeToken, 'DISPATCH'); IF TYPE='xlPie' THEN charttype := -4102; ELSIF TYPE='xl3DBar' THEN charttype := -4099; ELSIF TYPE='xlBar' THEN charttype := 2; ELSIF TYPE='xl3dLine' THEN http://emag.csdn.net - 18 - 2005 年 5 月 4 期 总第 4 期
  • 19. 《CSDN 社区电子杂志——Oracle 杂志》 charttype:= -4101; END IF; ordcom.SetArg(charttype,'I4'); i:=ordcom.Invoke(Chart1Token,'ChartWizard', 2, DummyToken); i:=ordcom.DestroyObject(RangeToken); i:=ordcom.DestroyObject(ChartObjectToken); i:=ordcom.DestroyObject(ChartObject1); i:=ordcom.DestroyObject(Chart1Token); RETURN i; END InsertChart; FUNCTION SaveToFile(filename VARCHAR2) RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.SetArg(filename,'BSTR'); i:=ordcom.Invoke(WorkBookToken, 'SaveAs', 1, DummyToken); -- 保存文件 IF (i!=0) THEN ordcom.GetLastError(err_src, err_desc, err_hpf, err_hpID); raise_application_error(-20000,err_src || err_desc || err_hpf || err_hpID); END IF; RETURN i; END SaveToFile; FUNCTION CloseExcel RETURN BINARY_INTEGER IS BEGIN ordcom.InitArg(); ordcom.InitArg(); ordcom.SetArg(FALSE,'BOOL'); i:=ordcom.Invoke(WorkBookToken, 'Close', 0, DummyToken); i:=ordcom.DestroyObject(WorkBookToken); ordcom.InitArg(); i:=ordcom.Invoke(WorkBooksToken, 'Close', 0, DummyToken); i:=ordcom.DestroyObject(WorkBooksToken); i:=ordcom.Invoke(applicationToken, 'Quit', 0, DummyToken); -- 关闭所有句柄 i:=ordcom.DestroyObject(WorkSheetToken); i:=ordcom.DestroyObject(WorkSheetToken1); i:=ordcom.DestroyObject(applicationToken); i:=ordcom.DestroyObject(ChartObjectToken); i:=ordcom.DestroyObject(Chart1Token); i:=ordcom.DestroyObject(hLines); i:=ordcom.DestroyObject(ChartObject1); i:=ordcom.DestroyObject(dummyToken); RETURN i; END CloseExcel; END oraExcel; http://emag.csdn.net - 19 - 2005 年 5 月 4 期 总第 4 期
  • 20. 《CSDN 社区电子杂志——Oracle 杂志》 成功创建 oraExcel 包后,最后创建使用包的存储过程,实现把数据表里的字符型、日期型和 数值型分别传到 Excel 工作表里,对数值型数据进行统计和使用 Excel 中的图表。该过程具体操作 步骤为: 创建 Excel 对象。 建立表头,设置列宽。 将游标数据传到工作表。 画表格。 设置字体属性。 插入图表。 保存为 Excel 格式文件,关闭 Excel 对象。 如下为 dp_toExcel 存储过程: CREATE OR REPLACE PROCEDURE dp_ToExcel IS CURSOR c1 IS SELECT ITS_ID,ITS_DATE,ITS_TOTAL FROM IT_SALE_TAB; n BINARY_INTEGER:=2; i BINARY_INTEGER; filename VARCHAR2(255); cellIndex VARCHAR2(40); cellValue VARCHAR2(40); cellColumn VARCHAR2(10); returnedTime VARCHAR2(20); currencyvalue DOUBLE PRECISION; dateValue DATE; xlThin BINARY_INTEGER:=2; xlEdgeLeft BINARY_INTEGER:=7; xlEdgeTop BINARY_INTEGER:=8; xlEdgeBottom BINARY_INTEGER:=9; xlEdgeRight BINARY_INTEGER:=10; xlInsideVertical BINARY_INTEGER:=11; xlInsideHorizontal BINARY_INTEGER:=12; BEGIN i:=oraExcel.CreateExcelWorkSheet(''); i:=oraExcel.setCellValues('A2', '序号', 'BSTR'); i:=oraExcel.setCellValues('B2', '日期', 'BSTR'); i:=oraExcel.setCellValues('C2', '销售', 'BSTR'); http://emag.csdn.net - 20 - 2005 年 5 月 4 期 总第 4 期
  • 21. 《CSDN 社区电子杂志——Oracle 杂志》 i:=oraExcel.setCellColWidth('B:B', 12.75,'CY'); -- 设置列宽 i:=oraExcel.setCellColWidth('C:C', 12.75,'CY'); n:=3; For c1_rec IN c1 LOOP cellColumn:=TO_CHAR(n); cellIndex:= 'A'||cellColumn; cellValue:= TO_CHAR(c1_rec.ITS_ID); i:=oraExcel.setCellValues(cellIndex, cellValue, 'BSTR'); cellIndex:= 'B' || cellColumn; dateValue:=c1_rec.ITS_DATE; i:=oraExcel.setCellValues(cellIndex, dateValue, 'DATE'); cellIndex:= 'C' || cellColumn; cellValue:=c1_rec.ITS_TOTAL; currencyValue:=cellValue; i:=oraExcel.setCellValuesReal(cellIndex, currencyValue, 'CY'); n:=n+1; END LOOP; i:=oraExcel.setCellValues('A'||n,'合计','BSTR'); i:=oraExcel.setCellValues('C'||n,'=SUM(C3:C'||to_char(n-1)||')','BSTR'); -- 画表格 i:=oraExcel.setCellLines('A1:C'||n,xlEdgeLeft,xlThin,'I2'); i:=oraExcel.setCellLines('A1:C'||n,xlEdgeTop,xlThin,'I2'); i:=oraExcel.setCellLines('A1:C'||n,xlEdgeBottom,xlThin,'I2'); i:=oraExcel.setCellLines('A1:C'||n,xlEdgeRight,xlThin,'I2'); i:=oraExcel.setCellLines('A1:C'||n,xlInsideVertical,xlThin,'I2'); i:=oraExcel.setCellLines('A1:C'||n,xlInsideHorizontal,xlThin,'I2'); -- 设置字体属性 i:=oraExcel.setCellFont('A1:C1','Size',20,'I2'); i:=oraExcel.setCellFont('A1:C1','Bold',1,'I2'); i:=oraExcel.callMethod('A1:C1','Merge'); -- 合并单元格 i:=oraExcel.setCellValues('A1:C1','合计','BSTR'); -- 插入图表 i:=oraExcel.InsertChart(350,200,250,250,'C3:C'||TO_CHAR(n-1),'xlPie'); SELECT TO_CHAR(SYSDATE, 'HH24MISS') INTO returnedTime FROM dual; filename:='D:testExcel' || returnedTime || '.xls'; i:=oraExcel.SaveToFile(filename); -- 保存文件 i:=oraExcel.closeExcel(); -- 关闭对象 END; 1.6. 小结 本文介绍如何从 PL/SQL 中直接调用 C 程序的外部例程,并以操作 Excel 对象为示例。在调用 http://emag.csdn.net - 21 - 2005 年 5 月 4 期 总第 4 期
  • 22. 《CSDN 社区电子杂志——Oracle 杂志》 该外部例程时,有如下相关的限制: 操作系统必需支持动态链接库(DLL)和共享库功能。 监听器和 extproc 进程必须运行在数据库所在的同一台机子上,不支持远程数据库。 extproc 唯一支持的是 C 例程,但可以通过先调用 C 外部例程去使用其它对象(如:COM 对象) 。 除了限制外,调用外部例程会引起额外的系统资源开销,在使用外部例程之前要考虑是否一 定要用到外部例程。 作者简介: 姓名:陈思童 网名:chanet CSDN 社区 Oracle 开发版主; 熟悉数据库开发、Oracle 数据库接口设计、数据库管理。 个人教育和成长经历: 信息管理专业;大学毕业后一直从事以 Oracle 为主的开发工作。 擅长的技术领域: 数据库开发、软件规划、系统分析。 研究方向: 数据库管理、数据仓库、电子商务。 目前的工作动态: 广州某软件公司;负责后台设计、数据库接口技术支持、数据库开发与维护工作。 个人Blog:http://blog.csdn.net/chanet MSN:cheasy@hotmail.com E-mail:chanet@oracle.com.cn OR chanet@163.com http://emag.csdn.net - 22 - 2005 年 5 月 4 期 总第 4 期
  • 23. 《CSDN 社区电子杂志——Oracle 杂志》 数据库复制 最简单的创建只读实体化视图站点的方法 本文作者: Kamus (kamusis@gmail.com ) 摘要:由于支持异构这一特点,Oracle 的高级复制通常被作为一种性价比超群的数据库同步 方案,但是由于 Oracle 高级复制的功能比较强大,所以配置步骤也显得有些麻烦。但是如果我们 的要求比较简单,比如说只有一个数据库用作日常业务,支持数据更新,另外一个数据库只需要 作一个同步的备份,最多支持只读的查询,那么其实只需要非常简单的步骤就可以实现这个目的。 本文给出最简单的步骤用以创建一个实体化视图站点,定时刷新,获取主站点中指定表的变 化,这个实体化站点可以作为查询服务器使用。 完整的配置步骤如下。对于支持数据更新的数据库我们称为主站点,对于同步的数据库我们 称为实体化站点。 1.1. 主站点上创建实体化视图日志表 CREATE MATERIALIZED VIEW LOG ON kamus.account2004; 1.2. 实体化视图站点上创建公用数据库链接 conn system/password CREATE PUBLIC DATABASE LINK orcl using 'ORCL'; 1.3. 实体化视图站点上创建刷新组,本例中 3 分钟刷新 一次 conn system/password BEGIN http://emag.csdn.net - 23 - 2005 年 5 月 4 期 总第 4 期
  • 24. 《CSDN 社区电子杂志——Oracle 杂志》 DBMS_REFRESH.MAKE ( name => 'kamus.test_repg', list => '', next_date => SYSDATE, interval => 'SYSDATE + 3/(24*60)', --此处的刷新时间可以根据需求调整 implicit_destroy => FALSE, rollback_seg => '', push_deferred_rpc => TRUE, refresh_after_errors => FALSE); END; / 1.4. 实体化视图站点上创建用户私有数据库链接 conn kamus/password CREATE DATABASE LINK orcl CONNECT TO kamus IDENTIFIED BY password; 1.5. 实体化视图站点上创建实体化视图 conn kamus/password CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY AS SELECT * FROM KAMUS.ACCOUNT2004@orcl; 1.6. 实体化视图站点上将创建的视图加入刷新组 conn kamus/password exec DBMS_REFRESH.ADD(name => 'kamus.TEST_REPG', list => 'kamus.ACCOUNT2004', lax => TRUE); 1.7. 测试 在主站点中更新 ACCOUNT2004 表,过 3 分钟检查实体化试图站点中的视图,发现更新已经 复制成功。 1.8. 总结 总结一下建立只读实体化视图站点的最简单方法: http://emag.csdn.net - 24 - 2005 年 5 月 4 期 总第 4 期
  • 25. 《CSDN 社区电子杂志——Oracle 杂志》 不需要创建其它的任何用户,比如复制环境中需要的传播者,刷新者,接收者等等 不需要创建任何复制组 不需要生成任何复制对象,不需要生成任何对象的复制支持 1.9. 附录 创建实体化视图产生ORA-600 [ksmovrflow], [kkznxddl.begin]错误的解决方法 如果测试环境中的 master site 是 Oracle10g,MV site 是 Oracle9.x 或者 8.1.x,当在 MV site 上创建 快速刷新的实体化视图时,可能会报 ORA-600 错误。 SQL> CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY AS SELECT * FROM KAMUS.ACCOUNT2004@orcl; CREATE MATERIALIZED VIEW KAMUS.ACCOUNT2004 REFRESH FAST WITH PRIMARY KEY AS SELECT * FROM KAMUS.ACCOUNT2004@orcl ORA-00600: internal error code, arguments: [ksmovrflow], [kkznxddl.begin], [], [], [], [], [], [] 这是Oracle10g的一个bug(Bug编号:3508674),只有当在Oracle8 或者 9 中创建基于Oracle10g的 实体化视图时才会发生。这个Bug在 10.1.0.3 Server Patch Set中被修复。 原因: Oracle10g 的 master table 中创建主键时候显式指定了主键的名称。比如执行了类似下面的命令 alter table table_name add constraint < constraint name> primary key (< col>); 解决方法: 删除这个主键,然后创建一个不指定名称的主键,由 Oracle 自动命名,如下: alter table ACCOUNT2004 add primary key(OCCURTIME, ACCTID, CURRENCYID); 这样产生的主键名称就变成 SYS_CXXXX。之后重新在 MV site 上创建实体化视图即可。 http://emag.csdn.net - 25 - 2005 年 5 月 4 期 总第 4 期
  • 26. 《CSDN 社区电子杂志——Oracle 杂志》 作者简介: 张乐奕,网名 kamus 曾任 ITPUB Oracle 认证版版主,现任 itpub Oracle 管理版版主。 现任职于北京某大型软件公司,首席DBA,主要负责证券行业的全国十数处核心交易系统数据库管 理及维护工作。 热切关注Oracle技术和其它相关技术,出没于各大数据库技术论坛,目前是中国最大的Oracle技 术论坛www.itpub.net的数据库管理版版主。 阅读更多技术文章和随笔可以登录我的个人blog。 http://blog.dbform.com。 http://emag.csdn.net - 26 - 2005 年 5 月 4 期 总第 4 期
  • 27. 《CSDN 社区电子杂志——Oracle 杂志》 Oracle 高级复制冲突解决机制的研究 —— dbms_rectifier_diff 及手动解决 Oracle 高级复制中的冲突 本文作者: eygle (eygle.com@gmail.com ) 摘要:本文简要探讨 dbms_rectifier_diff 包的机制及如何手动解决 Oracle 高级复制中的冲突。 关于 dbms_rectifier_diff 的使用请参考: http://www.eygle.com/archives/2005/01/eoadbms_rectifi.html 实际上 Oracle 的 dbms_rectifier_diff.DIFFERENCES 过程,内部操作就是执行两个 minus 操作 把两边的差异记录下来,作为冲突解决的数据。 这部分后台操作可以通过跟踪 Oracle 进程得到: SQL> alter session set events '10046 trace name context forever,level 12'; Session altered. Elapsed: 00:00:00.02 SQL> begin dbms_rectifier_diff.DIFFERENCES( 2 SNAME1 =>'HAWA', 3 ONAME1 =>'TEST', 4 REFERENCE_SITE =>'AVATAR.COOLYOUNG.COM.CN', 4 SNAME2 =>'HAWA', 6 ONAME2 =>'TEST', 7 COMPARISON_SITE =>'AUTHAA.COOLYOUNG.COM.CN', 8 WHERE_CLAUSE =>NULL, 9 COLUMN_LIST =>NULL, 10 MISSING_ROWS_SNAME =>'HAWA', 11 MISSING_ROWS_ONAME1 =>'MISSING_ROWS_TEST', 12 MISSING_ROWS_ONAME2 =>'MISSING_LOCATION_TEST', http://emag.csdn.net - 27 - 2005 年 5 月 4 期 总第 4 期
  • 28. 《CSDN 社区电子杂志——Oracle 杂志》 13 MISSING_ROWS_SITE =>'AVATAR.COOLYOUNG.COM.CN', 14 MAX_MISSING =>500, 15 COMMIT_ROWS =>100 16 ); 17 end; 18 / PL/SQL procedure successfully completed. Elapsed: 00:00:01.97 SQL> alter session set events '10046 trace name context off'; 从跟踪文件中我们可以清晰的看到(注意你所定义的所有参数在此都会有所体现): 首先是一个正向 Minus DECLARE row_count BINARY_INTEGER := 0; missing_rows BINARY_INTEGER := 0; arowid ROWID; CURSOR c IS SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" FROM "HAWA"."TEST" MINUS SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" FROM "HAWA"."TEST"@authaa.coolyoung.com.cn; BEGIN FOR r IN c LOOP missing_rows := missing_rows + 1; IF missing_rows > 500 THEN COMMIT; EXIT; END IF; INSERT INTO "HAWA"."MISSING_ROWS_TEST" ("DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" ) http://emag.csdn.net - 28 - 2005 年 5 月 4 期 总第 4 期
  • 29. 《CSDN 社区电子杂志——Oracle 杂志》 VALUES (r."DATLOGONTIME", r."NUMGENDER", r."NUMSTATUS", r."NUMUSERID", r."VC2IP", r."VC2USERNAME" ); SELECT ROWID INTO arowid FROM "HAWA"."MISSING_ROWS_TEST" WHERE ( datlogontime = r."DATLOGONTIME" OR (datlogontime IS NULL AND r."DATLOGONTIME" IS NULL) ) AND ( numgender = r."NUMGENDER" OR (numgender IS NULL AND r."NUMGENDER" IS NULL) ) AND ( numstatus = r."NUMSTATUS" OR (numstatus IS NULL AND r."NUMSTATUS" IS NULL) ) AND (numuserid = r."NUMUSERID") AND (vc2ip = r."VC2IP" OR (vc2ip IS NULL AND r."VC2IP" IS NULL)) AND ( vc2username = r."VC2USERNAME" OR (vc2username IS NULL AND r."VC2USERNAME" IS NULL) ); INSERT INTO "HAWA"."MISSING_LOCATION_TEST" (present, absent, r_id ) VALUES ('AVATAR.COOLYOUNG.COM.CN', 'AUTHAA.COOLYOUNG.COM.CN', arowid ); row_count := row_count + 1; IF row_count >= 100 THEN COMMIT; row_count := 0; END IF; END LOOP; COMMIT; END; 其次是一个反向 Minus DECLARE row_count BINARY_INTEGER := 0; missing_rows BINARY_INTEGER := 0; http://emag.csdn.net - 29 - 2005 年 5 月 4 期 总第 4 期
  • 30. 《CSDN 社区电子杂志——Oracle 杂志》 arowid ROWID; CURSOR c IS SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" FROM "HAWA"."TEST"@authaa.coolyoung.com.cn MINUS SELECT "DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" FROM "HAWA"."TEST"; BEGIN FOR r IN c LOOP missing_rows := missing_rows + 1; IF missing_rows > 500 THEN COMMIT; EXIT; END IF; INSERT INTO "HAWA"."MISSING_ROWS_TEST" ("DATLOGONTIME", "NUMGENDER", "NUMSTATUS", "NUMUSERID", "VC2IP", "VC2USERNAME" ) VALUES (r."DATLOGONTIME", r."NUMGENDER", r."NUMSTATUS", r."NUMUSERID", r."VC2IP", r."VC2USERNAME" ); SELECT ROWID INTO arowid FROM "HAWA"."MISSING_ROWS_TEST" WHERE ( datlogontime = r."DATLOGONTIME" OR (datlogontime IS NULL AND r."DATLOGONTIME" IS NULL) ) AND ( numgender = r."NUMGENDER" OR (numgender IS NULL AND r."NUMGENDER" IS NULL) ) AND ( numstatus = r."NUMSTATUS" OR (numstatus IS NULL AND r."NUMSTATUS" IS NULL) ) AND (numuserid = r."NUMUSERID") AND (vc2ip = r."VC2IP" OR (vc2ip IS NULL AND r."VC2IP" IS NULL)) AND ( vc2username = r."VC2USERNAME" http://emag.csdn.net - 30 - 2005 年 5 月 4 期 总第 4 期
  • 31. 《CSDN 社区电子杂志——Oracle 杂志》 OR (vc2username IS NULL AND r."VC2USERNAME" IS NULL) ); INSERT INTO "HAWA"."MISSING_LOCATION_TEST" (present, absent, r_id ) VALUES ('AUTHAA.COOLYOUNG.COM.CN', 'AVATAR.COOLYOUNG.COM.CN', arowid ); row_count := row_count + 1; IF row_count >= 100 THEN COMMIT; row_count := 0; END IF; END LOOP; COMMIT; END; 经过这两个步骤的操作,Oracle 定位了冲突数据。 可是注意,如果在解决这个问题时你没有挂起复制,Oracle 得到的数据可能是存在问题的。 而且,如果你不指定 column list,那么两边的数据可能会因为某些特殊字段(如时间字段)的特殊 处理而存在差异。 那么这时候手工介入不可避免。 我们首先先把两个重要参数的用法说明一下。 一个是 WHERE_CLAUSE,另外一个是 COLUMN_LIST。 WHERE_CLAUSE 用于限定进行差异比较的范围,这可以极大的缩减结果集的数量,使用索 引加快访问速度等。 比如我这里使用 NUMGENDER=1,只比较性别为"女"这一部分用户数据。 http://emag.csdn.net - 31 - 2005 年 5 月 4 期 总第 4 期
  • 32. 《CSDN 社区电子杂志——Oracle 杂志》 COLUMN_LIST 用于限定比较字段,如果你能通过某个字段,如主键等确定数据差异,那么 你完全可以只比较单个字段。 而且显然可以轻易通过全索引扫描来完成比较,加快比较速度。 我这里使用 NUMUSERID,用户 ID 来比较。 但 是 注 意 , 这 样 的 比 较 结 果 中 将 只 包 含 NUMUSERID 信 息 , 当 然 我 们 可 以 轻 易 通 过 NUMUSERID 和原表的比较补全 MISSING_ROWS_TEST 表的信息。 begin dbms_rectifier_diff.DIFFERENCES( SNAME1 =>'HAWA', ONAME1 =>'TEST', REFERENCE_SITE =>'AVATAR.COOLYOUNG.COM.CN', SNAME2 =>'HAWA', ONAME2 =>'TEST', COMPARISON_SITE =>'AUTHAA.COOLYOUNG.COM.CN', WHERE_CLAUSE =>'NUMGENDER=1', COLUMN_LIST =>'NUMUSERID', MISSING_ROWS_SNAME =>'HAWA', MISSING_ROWS_ONAME1 =>'MISSING_ROWS_TEST', MISSING_ROWS_ONAME2 =>'MISSING_LOCATION_TEST', MISSING_ROWS_SITE =>'AVATAR.COOLYOUNG.COM.CN', MAX_MISSING =>500, COMMIT_ROWS =>100 ); end; / 这段代码供参考。 Ok,我们继续前面的讨论。 我们提到,如果存在差异,通常需要手工介入。 清楚了 DIFFERENCES 的原理,实际上我们完全可以手工来完成这个过程。 以下是我的手工操作步骤,目的是为了准确性及减轻数据库压力: http://emag.csdn.net - 32 - 2005 年 5 月 4 期 总第 4 期
  • 33. 《CSDN 社区电子杂志——Oracle 杂志》 首先创建一个 ID 差异表 这个表不是必须的,这里是为了清晰 SQL> create table hawa.prof as select NUMUSERID from hawa.hw_user where 1=0; Table created. Elapsed: 00:00:00.16 根据主键找到差异记录 注意这里取决于你的数据库产生差异的原因,我的差异由于初始数据不同步,即 A 全包含 B 并且,A>B。 SQL> insert into hawa.prof 2 select * from 3 ( 4 select NUMUSERID from hawa.HW_USERPROFILE 5 minus 6 select NUMUSERID from hawa.HW_USERPROFILE@authaa) 7 / 263 rows created. Elapsed: 00:00:32.49 创建记录表 SQL> create table hawa.missing_rows_hw_userprofile 2 as 3 select * from hawa.hw_userprofile where 1=0; Table created. Elapsed: 00:00:00.12 创建位置(Location)表 注 意 这 里 Oracle 需 要 记 录 缺 失 方 向 , 和 具 体 记 录 的 ROWID , 这 个 ROWID 来 自 missing_rows_hw_userprofile。 SQL> create table hawa.MISSING_LOC_hw_userprofile ( 2 present VARCHAR2(128), 3 absent VARCHAR2(128), http://emag.csdn.net - 33 - 2005 年 5 月 4 期 总第 4 期
  • 34. 《CSDN 社区电子杂志——Oracle 杂志》 4 r_id ROWID); Table created. Elapsed: 00:00:00.04 根据差异信息查询到完整信息 SQL> insert into hawa.missing_rows_hw_userprofile 2 select * from hawa.hw_userprofile where NUMUSERID in 3 (select * from hawa.prof); 263 rows created. Elapsed: 00:00:00.06 SQL> commit; Commit complete. Elapsed: 00:00:00.02 构造位置信息 注意这里的方向信息及 ROWID 信息。 SQL> insert into hawa.MISSING_LOC_hw_userprofile 2 select 'AVATAR.COOLYOUNG.COM.CN','AUTHAA.COOLYOUNG.COM.CN',rowid from hawa.missing_rows_hw_userprofile; 263 rows created. Elapsed: 00:00:00.00 SQL> commit; Commit complete. Elapsed: 00:00:00.06 纠正数据冲突 SQL> BEGIN DBMS_RECTIFIER_DIFF.RECTIFY( 2 SNAME1 =>'HAWA', 3 ONAME1 =>'HW_USERPROFILE', http://emag.csdn.net - 34 - 2005 年 5 月 4 期 总第 4 期
  • 35. 《CSDN 社区电子杂志——Oracle 杂志》 4 REFERENCE_SITE =>'AVATAR.COOLYOUNG.COM.CN', 5 SNAME2 =>'HAWA', 6 ONAME2 =>'HW_USERPROFILE', 7 COMPARISON_SITE =>'AUTHAA.COOLYOUNG.COM.CN', 8 COLUMN_LIST =>NULL, 9 MISSING_ROWS_SNAME =>'HAWA', 10 MISSING_ROWS_ONAME1 =>'MISSING_ROWS_HW_USERPROFILE', 11 MISSING_ROWS_ONAME2 =>'MISSING_LOC_HW_USERPROFILE', 12 MISSING_ROWS_SITE =>'AVATAR.COOLYOUNG.COM.CN', 13 COMMIT_ROWS =>100 14 ); 15 END; 16 / PL/SQL procedure successfully completed. Elapsed: 00:00:03.53 验证结果 SQL> select count(*) from hawa.HW_USERPROFILE; COUNT(*) ---------- 1746300 Elapsed: 00:00:02.22 SQL> select count(*) from hawa.HW_USERPROFILE@authaa; COUNT(*) ---------- 1746300 Elapsed: 00:00:00.21 SQL> select count(*) from hawa.HW_USERPROFILE; COUNT(*) ---------- 1746300 Elapsed: 00:00:00.59 SQL>select count(*) from hawa.HW_USERPROFILE@authaa; http://emag.csdn.net - 35 - 2005 年 5 月 4 期 总第 4 期
  • 36. 《CSDN 社区电子杂志——Oracle 杂志》 COUNT(*) ---------- 1746300 Elapsed: 00:00:00.20 SQL> select NUMUSERID from hawa.HW_USERPROFILE 2 minus 3 select NUMUSERID from hawa.HW_USERPROFILE@authaa ; no rows selected Elapsed: 00:00:23.51 SQL> 作者简介: 盖国强,网名 eygle 曾任 ITPUB MS 版版主,现任 itpub Oracle 管理版版主. 曾任职于某国家大型企业,服务于烟草行业,开发过基于 Oracle 数据库的大型 ERP 系 统,属国家信息产业部重点工程.同时负责 Oracle 数据库管理及优化,并为多家烟草企业提供 Oracle 数据库管理、优化及技术支持. 目前任职于北京某电信增值业务系统提供商企业,首席 DBA,负责数据库业务.管理全国 30 多个数据库系统。项目经验丰富,曾设计规划及支持中国联通增值业务等大型数据库系统. 实践经验丰富,长于数据库诊断、性能调整与 SQL 优化等。对于 Oracle 内部技术具有 深入研究。 高级培训讲师,培训经验丰富,曾主讲 itpub dba 培训及 itpub 高级性能调整等主要课 程. 《Oracle 数据库 DBA 专题技术精粹》一书的主编及主要作者. 你可以在http://www.eygle.com上找到关于作者的更多信息. http://emag.csdn.net - 36 - 2005 年 5 月 4 期 总第 4 期
  • 37. 《CSDN 社区电子杂志——Oracle 杂志》 数据库高可用性 SharePlex for Oracle 本文作者: Quest Software China 1.1. 前言 在企业信息化进程不断加快的今天,保持业务的连续性是企业用户进行数据存储时必须考虑 的重要方面。灾难的出现可能导致生产停顿、客户满意度降低,减少企业的竞争力。如何安全、 可靠、完整地保存数据,实现系统的灾难恢复是市场竞争的需要,更是进一步提高服务水平和改 善服务质量、提升业务支撑能力的重要技术手段。 目前,很多厂家都提供容灾保护的产品,主要包括基于存储、逻辑卷、主机、数据库物理方 式和数据库逻辑方式的各种复制技术。根据复制层面的不同,实现的技术以及容灾效果各不相同。 Quest Software 的 SharePlex for Oracle 通过数据库逻辑层的复制技术,可以方便地实现基于 Oracle 数据库的容灾保护,具有对源系统资源占用少,对网络资源占用少,支持异构环境和不同的复制 拓扑,保持事物一致性的特点。在开放异构环境、异地容灾、容灾系统可访问的环境中具有非常 大的优势。 通过 SharePlex for Oracle,可以帮助企业建立一个全面的、整体的容灾方案,最大限度地保证 业务系统的连续性和业务数据的可恢复性。 1.2. 高可用容灾方案设计 1.2.1. 高可用容灾系统的影响因素 影响应用系统可用性主要有三方面的因素,计划外的系统停机、计划内的维护操作和灾难恢 复。 http://emag.csdn.net - 37 - 2005 年 5 月 4 期 总第 4 期
  • 38. 《CSDN 社区电子杂志——Oracle 杂志》 1.2.2. 计划外的系统停机 计划外的系统停机指由于应用系统故障导致的系统不可用。减少计划外的停机时间是应用系 统设计人员和管理人员面临的主要任务,虽然每个业务系统都在硬件、软件和人员方面投入很多, 但每年计划外的停机时间还是不可避免的发生,造成了很多不可避免的经济损失。一般来说,计 划外的系统停机主要是由于以下原因引起的。 人为错误。如用户具有过多的权限,从而可以访问没有被授权的一些数据。或者数据库管理 人员过度劳累导致的错误。 硬件/软件出错。硬件和软件失败是不可避免的现象,而且随着数据库系统使用年限的增加而 变得更加脆弱。通常由于硬件/软件出错所引起的故障包括应用程序出错、数据库出错、操作 系统故障,如操作系统死机等以及硬件故障,如硬盘或网卡损坏等。 环境失败。环境失败指由于外部环境改变导致系统不可用或无法有效地进行数据库管理。如 断电,工人罢工等等。 1.2.2.1. 计划内的维护操作 系统操作人员经常提到的一个术语就是“维护”。大多数维护操作会影响到系统的可用性和性 能。由于进行主动系统维护所引起的停机时间被称为计划内停机时间。对于每个数据库应用来说, 每年或每月都需要一定的计划内停机时间,因为停机时间可以控制,停机操作对系统的影响也可 以预先通知到用户,因而计划内停机时间虽然发生频繁,对系统的影响可以控制在一定范围。 1.2.2.2. 灾难恢复 对于高可用需求的应用系统来说,自然灾害与人为灾害始终存在。自然原因引起的灾难包括 地震、洪水、火灾、飓风、恐怖活动、战争、暴乱活动等,人为因素导致的数据库不可用包括故 意破坏。这些灾难发生的概率非常低,但是如果一旦发生,对严重依赖于数据的企业是致命的打 击,甚至导致企业无法继续运营。 在灾难发生的情况下,数据恢复成为高可用性管理的首要任务,数据备份、特别是异地数据 备份是成功实现灾难恢复的核心。企业需要在保证业务数据恢复的情况下保持业务系统的连续性。 http://emag.csdn.net - 38 - 2005 年 5 月 4 期 总第 4 期
  • 39. 《CSDN 社区电子杂志——Oracle 杂志》 1.2.3. 高可用容灾系统的建设目标 系统的容灾和高可用方案必须能够应付所有可能引起计算机系统失效的问题。应用系统高可 用性和容灾方案需要满足两方面的要求: 1.业务系统的连续性 保持业务系统的连续性,意味着无论是由于硬件,软件或电源的失效都不应中断信息中心的 处理工作;实现业务的连续性需要减少或消除计划外停机时间,控制计划外停机时间对系统的影 响,在灾难发生时间进行业务系统的快速接管,这些主要通过各个层次的冗余技术实现的。 2.业务数据的可恢复性 业务数据的可恢复性从本质上来说是业务系统连续性的一个子集。如果数据出现问题而不能恢复, 业务系统的连续性无从谈起。因为数据对严重依赖于信息系统的企业非常重要,数据的可恢复性 一直是高可用性系统的一个重点考虑因素。业务数据的可恢复性是通过数据备份和冗余的数据拷 贝完成的。数据库复制和硬件复制都是用于这个环境的一些成熟技术。业务数据的可恢复性主要 考虑因素为备份数据的安全性,需要确保在任何情况下,包括容灾发生时备份数据都可以有效地 进行恢复。同时,数据丢失也是一个非常重要的评价指标。 1.2.4. 建设容灾系统的考虑因素 因为要建立整个应用系统的冗余备份,容灾系统是一个非常昂贵的系统,在容灾系统建设时 需要考虑以下因素: 容灾距离: 根据灾备中心建设的目的不同,灾备中心的建设需要考虑灾备中心的距离。一般来说,容灾 距离有本地和同城、异地三种方式。 异地容灾方案中,灾备中心和主中心的距离较远,如北京到上海。异地容灾可以有效地防止 由于本地灾难发生引起数据损失,但是实施成本很高、为了保障业务系统的性能一般采用同步数 据拷贝方式,这样会存在一定的数据损失,同时将应用系统切换到灾备中心的工作也非常繁琐。 一般来说,异地灾备中心建设的主要目的提供业务数据的恢复能力。 同城容灾方案中,灾备中心和主中心距离在几十公里以内。同城容灾可以有效地提供业务数 据的恢复能力以及应用快速接管能力。根据业务系统对数据访问以及数据丢失的需求,数据复制 可以采用同步或异步两种方式。 同地容灾指灾备系统和主中心在一个地理位置。一般来说,它可以和现有的其他可用性技术, 如 Cluster 结合,提供更高级别的高可用性。同时,很多同地容灾解决方案提供灾备中心的数据访 http://emag.csdn.net - 39 - 2005 年 5 月 4 期 总第 4 期
  • 40. 《CSDN 社区电子杂志——Oracle 杂志》 问能力。 为了有效地进行容灾,很多关键的业务系统建立两个系统,同城灾备中心和异地灾备中心, 同城灾备中心由生产系统采用同步方式进行数据复制,异地灾备中心由同城灾备中心采用异步方 式进行数据复制。 数据丢失 企业能忍受的数据丢失和具体处理的业务有关。例如:财务系统的数据很难承受任何损失, 而电信营帐系统在灾难发生时可以允许少量的数据丢失。目前,虽然有很多方案可以做到“零数据 丢失“,但企业往往为此支付高昂的费用,生产系统的性能也会受到很大影响。从业务的角度企业 能够承受德考虑数据丢失问题可以帮助企业在容灾方案上做出适合企业自身特点的选择。 应用切换时间 容灾系统建设的一个重要目的是保障业务系统的连续性。在灾难发生或业务系统出现问题时 间,将应用快速地切换到灾备系统可以最大程度地减少系统的停计时间。当灾难发生,启用灾备 中心需要采取一系列的措施。如将网络、电话线路切换到新的地点,启动操作系统、数据库,进 行应用程序的切换等等。一般来说,容灾系统的切换时间应该控制到 30 分钟以内。 主系统的可恢复性 主系统的可恢复性主要指数据的恢复,将应用切换灾备系统后,业务的连续性得以保持,主 系统的恢复时间应该控制在一天到几天之内。数据恢复的关键问题在于数据的可恢复性,以及恢 复过程中如何和灾备中心的数据保持一致。 目标系统的可访问性 目标数据可访问能够提高容灾系统的投资回报,增加容灾系统的利用价值。企业可以将目标 系统作为报表查询、统计分析等系统的数据源,减轻源系统的压力,使投资变为可用,而不是单 存的冷备闲置。同时,目标数据的在线使用可以保障数据的准确性,从而避免容灾系统长期冷备, 数据错误而无人发现的情况,能够确保容灾系统在灾难发生时被有效接管,进行数据恢复。 对源系统的影响。 灾备中心的建设是对现有系统的扩展和补充,不能因为灾备中心影响当前业务系统的性能, 导致系统的可用性降低。 网络资源的使用。 网络资源的使用对于容灾系统特别是异地容灾系统非常重要。在网络上传输的数据量大小直 接决定数据传输的实时性,同时,网络资源占用会影响灾备中心后期的网络使用费用。 容灾环境的开放性。 组成数据库应用系统的环境非常复杂,主机、存储、数据库是容灾环境的三个主要组件,支 持开放环境,例如容灾系统支持不同的操作系统和数据库、不同的磁盘阵列、不同的主机系统会 有效地适应未来的扩展需求,充分保护投资。 http://emag.csdn.net - 40 - 2005 年 5 月 4 期 总第 4 期
  • 41. 《CSDN 社区电子杂志——Oracle 杂志》 实施成本是在充分评估了上述内容后需要考虑的又一个重要因素。事实上,在建立容灾系统时, 一个对业务系统没有任何影响、没有任何数据损失、容灾距离足够远的方案是很难实现的。企业 需要了解自己的需求,建立适合自身特点的容灾系统。双数据中心环境下的有效冗余和网络结构 1.2.5. 容灾系统的实现技术 1.2.5.1. 基于磁带拷贝的传统灾难备份方式 利用磁带拷贝进行数据备份和恢复是最常见的传统灾难备份方式。这些磁带拷贝通常都是按 天,按周或按月进行组合保存的。 使用这种方式的数据拷贝通常是存储在盘式磁带或盒式磁带上,并存放在远离基本处理系统 的某个安全地点。存储到安全地点的磁带拷贝,其上的数据已有数小时的延迟,而在灾难或各种 故障出现系统需要立即恢复,必须将磁带提取出来,并运送到恢复地点,通常还要滞延几个小时。 基于磁带拷贝方式的传统灾难备份方式有着明显的缺陷,越来越不适合用户不断发展的业务系统 的需要。其备份和恢复过程非常复杂,数据延迟较大,磁带管理困难,数据恢复必须按照正确的 顺序,出错的可能性也较大。 1.2.5.2. 数据库方式 数据库复制是目前最流行的高可用解决方案。每种数据库系统来实现的机制和方式略有不同, 但都包括逻辑复制和物理复制两种方式: 逻辑复制指针对数据库的逻辑层数据进行复制,复制的基本单位为数据库表以及表中所有的 数据,复制时采用标准的 TCP/IP 协议。这种复制方法的好处是复制的数据量少,网络资源占用低, 在复制的过程中目标数据库可以被访问,企业可以将目标系统用于报表和查询系统。同时因为目 标数据库处于启动状态,接管时不需要重新启动数据库,接管可以接近实时。 物理复制方法主要通过日志文件的传送和应用实现的。数据库交易的复制机制利用日志的这 种特性,在生产中心将日志传输到灾备中心;如果灾备中心的数据库结构和生产中心的数据库结 构保持一致,则灾备中心的数据库对日志中记载的交易执行前滚操作,即实现了对灾备中心数据 库数据的更新。 数据库级别的复制可以支持计划内停机时间、计划外的停机时间和应用可以允许一些损失的 情况下进行灾难恢复。 http://emag.csdn.net - 41 - 2005 年 5 月 4 期 总第 4 期
  • 42. 《CSDN 社区电子杂志——Oracle 杂志》 1.2.5.3. 服务器卷方式 服务器卷方式复制嵌入到操作系统的卷管理系统中,卷发生的变化分为结构的变化和卷内容 的变化。这种复制方式可以复制卷内容的变化。 服务器卷方式有两种复制方式,同步方式和异步方式。同步方式采用数据库两阶段提交的方 法,对源系统的影响非常大。异步方式从数据的一致性保障方面存在问题。 由于卷复制部件使用服务器 CPU、Memory 资源,使用标准的 TCP/IP 网络,对业务的正常运 行产生的较大的性能影响。 使用服务器卷方式进行复制,必须使用专用的卷管理软件,整个应用系统的结构需要根据卷 管理的要求经过严格的设计和重新划分,同时,在后期的维护过程中也需要对卷结构的变化进行 同步的维护,从而增加实施和维护方面的一些困难。 服务器卷方式复制对服务器的硬件平台、数据库版本有严格限制,局限于主机同构环境。 1.2.5.4. 智能存储系统方式 智能存储方式利用磁盘系统自身的处理能力,通过磁盘系统之间的通道连接复制磁盘系统内 的数据更新,从而在异地中心保存生产数据的记录。利用磁盘复制可以独立于服务器、操作系统、 卷管理系统、数据库、文件系统、中间件、应用程序。 和服务器卷方式一样,智能存储两种复制方式,同步方式和异步方式。同步方式采用数据库 两阶段提交的方法,对源系统的影响非常大。异步方式从数据的一致性保障方面存在问题。 智能存储系统方式复制使用存储上的 CPU 资源,但对 IO 资源的消耗比较大。这种方式复制 速度很快,但这种复制方式对存储依赖非常强,主备服务器必须使用同样的存储设备,依赖于专 有网络。因为在存储级进行复制,目标数据库处于不可用状态。当需要应用切换时,必须停止复 制过程,Mount 复制卷组,将操作系统启动,启动数据库,进行数据库恢复。所有这些工作一般 手工进行,需要花费一定的时间。 采用智能存储系统方式进行复制,源系统和目标系统的硬件平台、操作系统、数据库版本必 须一致。复制的内容包括所有底层数据,占用的网络带宽较高。而且目标系统无法访问。 1.3. SharePlex for Oracle 介绍 目前,很多厂家都提供容灾保护的产品,主要包括基于存储、逻辑卷、主机、数据库物理方 式和数据库逻辑方式的各种复制技术。根据复制层面的不同,实现的技术以及容灾效果各不相同。 Quest Software 的 SharePlex for Oracle 通过数据库逻辑层的复制技术,可以方便地实现基于 Oracle http://emag.csdn.net - 42 - 2005 年 5 月 4 期 总第 4 期
  • 43. 《CSDN 社区电子杂志——Oracle 杂志》 数据库的容灾保护,具有对源系统资源占用少,对网络资源占用少,支持异构环境和不同的复制 拓扑,保持事物一致性的特点。在开放异构环境、异地容灾、容灾系统可访问的环境中具有非常 大的优势。 1.3.1. SharePlex for Oracle 结构 基本结构 下图所示为 SharePlex for Oracle 的基本结构,其中涉及较多的技术细节。 图 1-1 Shareplex 基本结构 数据捕获 SharePlex for Oracle 中由捕获进程来收集发生变化的数据,此进程的独特之处在于它几乎不对 生产数据库带来任何开销。 数据传输 SharePlex 结合其自己的网络协议和 TCP/IP 协议来完成源和目标系统之间的数据传输。其相 关的进程确保数据的正确接收和网络数据包的正确顺序,从而提供网络传输冗余,确保数据的完 整。整个数据传输过程无需其它的中间件。 应用数据 应用进程将传送到目标系统中的信息转化为 SQL 语句,然后采用标准的 SQL*Plus 方式将 SQL 语句发送给 Oracle 执行。 SharePlex 能够实现精确复制的一个重要原因就是其能保证从源数据库到目标数据库的 Oracle 读一致性,不但按顺序复制事务,而且也复制上下文信息。由于 SharePlex 将源数据库中发生变化 http://emag.csdn.net - 43 - 2005 年 5 月 4 期 总第 4 期
  • 44. 《CSDN 社区电子杂志——Oracle 杂志》 的全部事务信息都复制到目标数据库中,因此 SharePlex 复制方案用于灾难恢复系统中是足够可靠 的。 1.3.2. SharePlex for Oracle 配置方案 SharePlex 提供多种不同的配置方式以满足高可用性和负载均衡需求。主要包括: 单向复制 SharePlex 可以将源系统的数据实时复制到目标系统,从而建立一个可以被访问的即席查询和 报表系统。目标系统可以是源系统的全集和子集。通过将查询和报表系统放在不同的数据库实例 中运行,可以平衡服务器负载并提高 OLTP 类生产系统的性能。 高可用性 保证数据高可用性和数据库系统能够从灾难中迅速恢复是一个非常具有挑战性的工作。 SharePlex for Oracle 可以通过 LAN 或 WAN 进行复制,这样当生产环境出现紧急事件或要进行例 行维护时,可以将应用切换到复制数据库中。有了生产数据库的实时拷贝,用户可以保证应用系 统 7*24 不间断运行的情况下进行维护工作,如进行操作系统和数据库的升级等等。 分布处理 多数据源配置允许你将不同的用户分布到不同的服务器,让每个数据库能够反映其他数据库 的变化。在这种配置模式下,SharePlex 采用必要的冲突处理机制来解决可能发生的冲突。 广播和集中复制 SharePlex for Oracle 通过 LAN 或 WAN 进行实时复制,将生产数据库中的数据拷贝到需要它 们的地方。对广播复制来说,远程用户可以访问这些实时数据而不用登录生产服务器。因此,提 高了网络性能和生产环境下的 OLTP 应用的性能。 http://emag.csdn.net - 44 - 2005 年 5 月 4 期 总第 4 期
  • 45. 《CSDN 社区电子杂志——Oracle 杂志》 企业环境的数据分布 SharePlex 支持层叠复制,可以向不是直接相连的数据库复制数据。使用这种配置,可以在远 程数据库间进行复制(如从北京到上海)。SharePlex 支持多种复杂的场景来满足复制需求。 1.3.3. Shareplex for Oracle 特点 1.3.3.1. 快速精确和低负载 SharePlex 是非常快速的,同时保证了复制数据的精确性。在源数据库一端,SharePlex 严格地 遵守读一致性模式。在目标数据库一端,SharePlex 使用标准 SQL 提交事务,并保证操作次序和会 话上下文的一致。 基于 Log 的复制方式对源数据库和系统所带来资源开销非常小,因为复制操作只是读取操作 系统的日志文件,同时通过 TCP/IP 方式而不是采用中间件方式传输只发生改变的数据也使网络负 载降至最低。 1.3.3.2. 可扩展及全面 每秒钟可针对数千个表复制超过一千个以上事务的处理能力意味着 SharePlex 可以处理企业级 的业务数据,可以满足企业大数据量的吞吐需求。实际环境中的吞吐速率是受服务器性能、网络 带宽和事务的复杂程度所影响的。 SharePlex 提供的完全复制程度是其它软件复制工具所不具备的。SharePlex 支持带长列的表、 http://emag.csdn.net - 45 - 2005 年 5 月 4 期 总第 4 期
  • 46. 《CSDN 社区电子杂志——Oracle 杂志》 带参照完整性约束的表、没有主键的表、序列等等的复制。此外,SharePlex 复制 ALTER TABLE 等命令,使它可以不需要其它软件复制工具就复制 DDL 活动。 1.3.3.3. 灾难恢复 SharePlex 在设计时已经将性能和容灾因素考虑在内。SharePlex 可以容忍实例失败、系统失败 和网络失败。一般情况下,在源系统中运行的事务一旦被写入 log,SharePlex 立即将其发送到目标 系统。然而,如果发生问题,SharePlex 可以在源系统或目标系统进行事务排队(为了最小化对源系 统的影响,排队位于 Oracle 源实例之外)。例如,如果网络宕掉或目标系统宕掉,SharePlex 将源系 统中的事务排队。当网络或系统恢复后,SharePlex 将自动提交被排队的数据并清空队列文件。 1.3.3.4. 灵活配置和简洁管理 SharePlex 可以被灵活配置,以支持各种复制策略。包括单向复制、双向复制、广播复制、集 中复制及多层复制等。 SharePlex 是独立的软件,不需要修改与数据库进行交互的应用程序和数据库本身。因此,安 装非常简洁。配置和改变复制策略不影响源数据库系统中的生产活动。管理员可以用 Windows 界 面或服务器端的命令行管理和监控复制操作的各个方面。 1.3.4. SharePlex for Oracle 适用场合 应用容灾 企业开始比以往任何时候更注重对关键业务数据进行及时的保护,因为关键业务数据的丢失 可能会给企业带来不可估量的损失。 SharePlex 为业务系统提供灾难恢复能力,容灾系统中的硬件环境又可用来降低系统维护工作 中的停机时间。这并不与企业的容灾方案相矛盾,因为事务可被发送到系统中的远程节点上。 SharePlex 支持多种配置方案,包括对等配置方案,在这种配置方案中,两个数据库都处于可 用状态,因而可实现快速的失败接管。在容灾发方案中没有比这种失败接管更快的方法了。 减少有计划的停机时间 有计划的停机也可能对企业的服务水平、客户满意程度甚至股价等带来影响,而据估计企业 80%的停机是有计划的行为。 利用 SharePlex,企业可几乎完全消除系统的停机时间而不用考虑在此期间进行何种维护工 http://emag.csdn.net - 46 - 2005 年 5 月 4 期 总第 4 期
  • 47. 《CSDN 社区电子杂志——Oracle 杂志》 作、哪个操作系统会受到影响,甚至不用考虑数据库版本的问题及对硬件环境进行何种操作。 负载平衡 SharePlex 可以将源系统的数据实时复制到目标系统,从而建立一个可以被访问的即席查询和 报表系统。目标系统可以是源系统的全集和子集。通过将查询和报表系统放在不同的数据库实例 中运行,可以平衡服务器负载并提高 OLTP 类生产系统的性能。一方面,可以减少 OLTP 应用和查 询报表应用之间的磁盘 I/O 冲突,提高 OLTP 应用的效率。另一方面,SharePlex 支持不同模式间 的复制。可以分别面向 OLTP 和查询系统的使用特点来进行设计,如建立索引,设置数据库表的参 数等等。 在这种配置环境下,SharePlex 在线事务处理可以获得很好的性能,而决策支持和报表处理可 在不影响正常业务的情况下进行。 当一种单一的数据复制模式不能满足企业的业务扩展需求和系统性能时,很容易利用 SharePlex 建立另外的复制模式,从而进一步扩展系统和提高报表处理的性能。 系统移植 尽管企业从规划设计良好的业务系统中收益,但也不得不面临系统移植和升级这一挑战。数 据集中、技术的推陈出新和服务器的移植都是导致必须进行系统移植的原因之一。 SharePlex 可确保在进行以上工作时正常的事务处理得以继续进行。源系统的功能不受到任何 影响,SharePlex 只捕捉移植过程中发生变化的事务并将它们排队保存。当移植工作结束后,这些 被保存的事务将被应用到新系统中并进行数据同步工作。一旦数据同步后,用户活动会有非常短 暂的停顿,在此瞬间将完成系统的切换动作。 数据集中和广播 SharePlex 通过非常有效的管理控制机制来实现数据集中和广播。SharePlex 提供细化的数据筛 选功能,可按业务需要定制需要传输的数据,从而缓解和消除了数据传输过程中的安全和带宽问 题。例如,如果远程节点只需要有关本地员工的基本信息而无需薪水信息,那么只需利用 SharePlex 传输相关的数据行和字段即可。 支持数据仓库应用、实现更好的决策支持 越来越多的公司在建设决策支持系统。传统的数据抽取、转换和装载工具按照时间段处理数据而 不能进行实时的数据处理,因而决策支持系统就不能真正体现出太大的价值。SharePlex 可以实时 捕捉、转换数据到决策支持系统中。 1.4. 容灾系统建立 http://emag.csdn.net - 47 - 2005 年 5 月 4 期 总第 4 期
  • 48. 《CSDN 社区电子杂志——Oracle 杂志》 1.4.1. 容灾系统状态定义 为方便论述,本节模拟地点 A 和 B,两地各有一套运行在 Oracle 上的应用系统。通过 SharePlex for Oracle 建立数据复制,以 B 地点的系统作为 A 地点的备份。 正常情况下: 业务系统运行在地点 A,包括数据库实例、有关的文件、数据库数据、应用软件。 A 节点对外提供服务。 A 节点所有的有关的数据通过 SharePlex for Oracle 实时复制到 B 节点。 灾难发生的情况下,整个 A 地点无法正常提供服务: A 地点的业务将在 B 地点正常提供服务。当灾难发生时,主中心的数据库服务、 应用软件切换到灾备中心的灾备节点。灾备节点对外提供服务。 数据复制暂停。 对主中心的数据库和应用系统进行恢复。 计划内维护操作 当进行计划内的维护时,主中心的数据库服务、应用软件切换到灾备中心的灾备 节点。灾备节点对外提供服务。 SharePlex for Oracle 记录进行维护期间数据的变化,存储到灾备节点的队列。 当计划内的维护操作时完成时,将维护过程中的数据复制到 A 地点,将应用切换 到 A 地点系统。 1.4.2. 容灾系统的的配置过程 1.4.2.1. 初始化高可用及容灾环境 使用 SharePlex for Oracle 进行数据复制的前提是在主中心和灾备中心具有相同的数据。根据 用户对停机时间的要求、容灾环境和数据量的大小。可以采用 Oracle 自身提供的方法进行初始化 同步,包括:Oracle Cold Backup,Oracle Hot Backup,Export/import,Transprant tablespace 等等。 为了保证初始化同步过程中源系统的可用性,SharePlex 提供 Reconcile 功能,当使用 Oracle Hot backup 机制进行初始化同步时,通过 SharePlex 队列记录数据的变化。并在进行 post 的过程中 确认哪些数据通过 Recovery 进行恢复,把没有恢复的数据装载到数据库中。从而保证初始化同步 过程中源系统没有停机时间。 http://emag.csdn.net - 48 - 2005 年 5 月 4 期 总第 4 期
  • 49. 《CSDN 社区电子杂志——Oracle 杂志》 1.4.2.2. 配置 Shareplex 的 Fail-over ready 状态 为保证灾难发生时快速进行应用接管,需要配置 Fail-over ready 状态。 确保源系统和目标系统 SharePlex for Oracle 启动。 源系统中建立配置文件,目标系统建立反向配置文件。两个配置文件都处于激活状态。 在 Secondary 端保证没有对复制表的 DML 操作; 在 Secondary 端停止 export 进程,防止意外的数据操作改变源系统的数据。 运行脚本取消 secondary 系统用户(除了 splex)的 insert,update 和 delete 权限; 禁止 Secondary 中使用 trigger,cascade delete constraints,foreign-key constraints,check constrants,schedule jobs 等等。 定期备份 Shareplex 相关的文件,文件包括 Shareplex 的工作目录 /var/adm/.splex/Shareplex.mark oratab file /etc/services /etc/system /etc/group 操作系统 Shareplex 用户(默认为 Oracle 用户)的.profile 文件 1.4.2.3. 灾难发生时应用切换到灾备中心 灾难发生时的接管工作由以下步骤组成: 确认 Secondary 系统的 export 进程处于停止状态; 确保在队列中的所有数据复制到 Secondary 系统中。用 qstatus 命令查看 Secondary 系统 中的 post 进程,直到 backlog messages 一项为 0; 在 Secondary 系统上运行 SQL 脚本给用户赋权,包括 insert, update 和 delete; 在 Secondary 系统上运行 SQL 脚本 enable triggers 和 contraints; 切换应用系统到 Secondary 系统; 确保 Secondary 系统上的 Shareplex export 进程处于停止状态。 切换过程所需要的时间主要是上述 6 个步骤所需要的时间的总和。正常情况下能够充分满足 30 分钟以内的切换要求。 http://emag.csdn.net - 49 - 2005 年 5 月 4 期 总第 4 期
  • 50. 《CSDN 社区电子杂志——Oracle 杂志》 1.4.2.4. 容灾中心的数据恢复到主中心 从容灾中心的数据恢复到主中心的过程分为如下阶段: 阶段 1:在 Primary System 中恢复复制环境。 阶段 2:Purge 队列, 在 Primary System 中 Purge Capture,Export 和 Post 队列。因为 Primary System 的复制环境是通过备份的软件进行恢复的。队列的内容已经过期。 在 Secondary System 中 Purge Post 队列。原则上 Capture 和 Export 队列没有内容,而在 Post 队列中需要清除没有被提交的部分数据。 阶段 3:开始从 Secondary system 复制到 Primary System,保证 Primary System 的数据存 储在 Post 队列中,但不加载到数据库中。 阶段 4:同步数据,即在 Primary System 中重新建立新的数据库拷贝。 阶段 5:在 Primary System 中进行 Activate。 阶段 6:恢复 Object Cache。 阶段 7:将用户切换到 Primary System。 系统的恢复时间由上述的 7 个阶段构成,其中阶段 4 的时间较长,根据系统的数据量、目标 系统硬件选型不同,正常切换时间在 10-38 个小时之间。 1.4.2.5. 计划内系统维护 计划内的 Shareplex failover 接管 在 Primary 系统上停止用户对数据对象的访问; 在 Primary 系统,运行 flush 命令,此命令停机目标机器上的 post 进程,并将队列中的 内容装载到数据库中。 关闭 Primary 中的 SharePlex 和 Oracle 数据库。 运行脚本为 Secondary 系统的 oracle 用户赋 insert, update 和 delete 的权限; 运行脚本激活 Secondary 系统的 oracle trigger 和 contraints; 按照相应步骤重新部署用户和应用到 Secondary 系统; 切换用户到 Secondary 系统,但不要启动 export 进程; 计划内的 Shareplex failback 接管 打开 Primary 系统的 Oracle 数据库; Primary 系统上对 Triggers、 在 Foreign-key constraints、 Cascading delete constriants、Check constraints、Scheduled jobs that perform DML 进行修 http://emag.csdn.net - 50 - 2005 年 5 月 4 期 总第 4 期