三、 测试复制环境:

1、 DDL 操作

  源端操作:

    JSSWEB> create tablespace jsstbs datafile ¨/data/oradata/jssweb/jsstbs01.dbf¨ size 200m;

    Tablespace created.

    JSSWEB> create user jss identified by jss default tablespace jsstbs quota unlimited on jsstbs;

    User created.

    JSSWEB> grant connect,resource to jss;

    Grant succeeded.

    JSSWEB> alter system switch logfile;

    System altered.

  转到目标端查询:

    JSSSTR> select username from dba_users where username=¨JSS¨;

    USERNAME

    ------------------------------

    JSS

    JSSSTR> select name from v$tablespace;

    NAME

    ------------------------------

    SYSTEM

    TEMP

    UNDOTBS1

    SYSAUX

    USERS

    STRMTBS

    JSSTBS

    已选择7行。

    JSSSTR> select name from v$datafile;

    NAME

    ------------------------------------------------------------------------------------------------------------------------------------------------------

    /data/oradata/jssstr/system01.dbf

    /data/oradata/jssstr/undotbs01.dbf

    /data/oradata/jssstr/sysaux01.dbf

    /data/oradata/jssstr/users01.dbf

    /data/oradata/jssstr/strmtbs01.ora

    /data/oradata/jssweb/jsstbs01.dbf

    已选择6行。

  目标端操作:

    JSSSTR > conn jss/jss

    已连接。

    JSSSTR> create table t as select * from all_objects where rownum<10;

    表已创建。

    JSSSTR> conn / as sysdba

    已连接。

    JSSSTR> alter system switch logfile;

    系统已更改。

  源端查看:

    JSSWEB> conn jss/jss

    Connected.

    JSSWEB> select count(0) from t;

      COUNT(0)

    ----------

             9

  可以看到,用户/表空间/表均已成功创建,双向基本同步成功,不过如果你足够细心会发现这里头有一个问题,数据文件路径的问题,这个问题暂时搁下,后面再介绍解决方案,接着测试DML操作的同步情况。

2、 DML 操作

    JSSWEB> delete t;

    9 rows deleted.

    JSSWEB> commit;

    Commit complete.

    JSSWEB> conn / as sysdba

    Connected.

    JSSWEB> alter system switch logfile;

    System altered.

    JSSSTR> select count(0) from jss.t;

      COUNT(0)

    ----------

             0

    DML 同步成功。

3、 数据文件路径的匹配

  在第一步测试ddl创建表空间时,我们指定了数据文件路径,某些情况下,可能源端和目标端的路径并不相同(甚至源端路径在目标端不存在),如上例中我们的环境就是这样,因此我们希望源端路径到目标端后能够做适当转换,以避免出错。Streams不支持dataguard中使用的db_file_convert之类的参数,但是streams中提供了更强大的DDL handler,这里我们就通过DDL handler来解决这个问题。

  首先先将路径不正常的表空间删除(当然也可以不删而是通过命令修改,这里为了演示更加清晰首先删除该表空间,创建好DDL handler后再重建):

  双向复制,两边都是源,因此哪边执行删除都可以:

    JSSSTR> drop tablespace jsstbs including contents and datafiles;

    表空间已删除。

    JSSSTR> select name from v$datafile;

    NAME

    --------------------------------------------------------------------------------

    /data/oradata/jssstr/system01.dbf

    /data/oradata/jssstr/undotbs01.dbf

    /data/oradata/jssstr/sysaux01.dbf

    /data/oradata/jssstr/users01.dbf

    /data/oradata/jssstr/strmtbs01.ora

    JSSSTR> alter system switch logfile;

    系统已更改。

  到目标端看一看:

    JSSWEB> select name from v$datafile;

    NAME

    --------------------------------------------------------------------------------

    /data/oradata/jssweb/system01.dbf

    /data/oradata/jssweb/undotbs01.dbf

    /data/oradata/jssweb/sysaux01.dbf

    /data/oradata/jssweb/users01.dbf

    /data/oradata/jssweb/strmtbs01.ora

  OK ,成功删除。

  下面演示创建DDL handler解决源与目标端路径不同的问题,以我们这里遇到的问题为例,我们希望将/data/oradata/jssweb转换为/data/oradata/jssstr,那么,可以通过如下操作:

  连接到strmadmin用户,创建一个处理过程:

    JSSSTR> conn strmadmin/strmadmin

    已连接。

    JSSSTR> create or replace procedure file_convert (in_any IN ANYDATA) authid current_user is 

      2    ddl_lcr  SYS.LCR$_DDL_RECORD;

      3    ddl_text CLOB;

      4    rc       PLS_INTEGER;

      5  begin

      6    rc := in_any.GETOBJECT(ddl_lcr);

      7    DBMS_LOB.CREATETEMPORARY(ddl_text, true);

      8    ddl_lcr.GET_DDL_TEXT(ddl_text);

      9    ddl_text := replace(ddl_text,¨/data/oradata/jssweb¨,¨/data/oradata/jssstr¨);

     10    execute immediate to_char(ddl_text);

     11    DBMS_LOB.FREETEMPORARY(ddl_text);

     12  end;

     13  /

    过程已创建。

  提示:通过这种方式也可以很容易记录下所有操作过的ddl语句。

  设置ddl handler:

    JSSSTR> select apply_name from dba_apply;

    APPLY_NAME

    ------------------------------

    APPLY$_JSSWEB_31

    JSSSTR> exec DBMS_APPLY_ADM.ALTER_APPLY(apply_name  => ¨APPLY$_JSSWEB_31¨,ddl_handler => ¨strmadmin.file_convert¨);

    PL/SQL  过程已成功完成。

  查询dba_apply字典:

    JSSSTR> select apply_name,ddl_handler,status from dba_apply ;

    APPLY_NAME                     DDL_HANDLER                              STATUS

    ------------------------------ ---------------------------------------- --------

    APPLY$_JSSWEB_31               "STRMADMIN"."FILE_CONVERT"               ENABLED

  验证一下,源端重新创建表空间:

    JSSWEB> create tablespace jsstbs datafile ¨/data/oradata/jssweb/jsstbs01.dbf¨ size 200m;

    Tablespace created.

    JSSWEB> alter system switch logfile;

    System altered.

  目标端查看表空间创建情况:

    JSSSTR> select name from v$datafile;

    NAME

    --------------------------------------------------------

    /data/oradata/jssstr/system01.dbf

    /data/oradata/jssstr/undotbs01.dbf

    /data/oradata/jssstr/sysaux01.dbf

    /data/oradata/jssstr/users01.dbf

    /data/oradata/jssstr/strmtbs01.ora

    /data/oradata/jssstr/jsstbs01.dbf

    已选择6行。

  路径转换成功,不过注意哟,我们这里是双向复制,因此从完整性的角度说还应该在jssweb数据库中也创建一个ddl hander,以替换/data/oradata/jssstr为/data/oradata/jssweb,因操作步骤与此相同,这里就不演示了,涂废笔墨,非我所好。

  至此整库的复制环境搭建完成!