单机搭建oracle dg 实验与总结

来源:互联网 发布:网络大型策略游戏 编辑:程序博客网 时间:2024/06/05 08:57

实验环境:
主库:windows xp + oracle 11.1.0.1

数据文件 D:\oracle\oradata\DG1\DATAFILE

复制到:windows xp + oracle 11.1.0.1

数据文件 G:\Oracle\oradata\DG2\DATAFILE

简称 主库和复制库


一、primary侧的环境准备:
1,确保数据库归档状态
 
 
SQL> select log_mode from v$database; 
 
LOG_MODE 
------------ 
ARCHIVELOG 
 
2,Enable force logging
 
SQL> ALTER DATABASE FORCE LOGGING; 
 
Database altered. 

3,生成standby redolog
[sql]
alter database add standby logfile 'D:\ORACLE\ORADATA\DG1\ONLINELOG\redo05.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG1\ONLINELOG\redo06.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG1\ONLINELOG\redo07.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG1\ONLINELOG\redo08.log' size 50m;


4,修改primary参数文件spfile,需要设置以下8个参数
 
SQL> alter system set LOG_ARCHIVE_CONFIG='DG_CONFIG=(dg1,dg2)'; 
    
System altered. 
 
SQL> alter system set LOG_ARCHIVE_DEST_1='LOCATION=D:\oracle\arch VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=dg1'; 
 
System altered. 
 
SQL> alter system set LOG_ARCHIVE_DEST_2='SERVICE=dg2 LGWR ASYNC VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=dg2'; 
 
System altered. 
 
SQL> alter system set LOG_ARCHIVE_DEST_STATE_1=ENABLE; 
 
System altered. 
 
SQL> alter system set FAL_SERVER=dg2; 
 
System altered. 
 
SQL> alter system set FAL_CLIENT=dg1; 
 
System altered. 
    
SQL> alter system set DB_FILE_NAME_CONVERT='D:\ORACLE\ORADATA\DG1\DATAFILE\','G:\Oracle\oradata\DG2\DATAFILE' scope=spfile; 
 
System altered. 
 
SQL> alter system set LOG_FILE_NAME_CONVERT='D:\oracle\arch','G:\oracle\arch' scope=spfile; 
 
System altered. 

二、修改sql*net相关文件,确保网络环境准备,确保互相tnsping通
listener.ora
SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
     (GLOBAL_DBNAME = standby)
     (ORACLE_HOME = /oracle/app/oracle/product/11.2.0/db_1)
     (SID_NAME = standby3)
    )
   )
 
 
SID_LIST_LISTENER =                                           ------此处需要手动编辑sid列,静态监听,否则报错ORA-12514
(SID_LIST =
  (SID_DESC =
    (SID_NAME = dg2)
    (ORACLE_HOME = D:\oracle\product\11.2.0\dbhome_1)
  )
 )

 

LISTENER =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.6.190)(PORT = 1521))
  )
 
  
tnsnames.ora
 
DG1 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.6.190)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = dg1)
    )
  )

DG2 =
  (DESCRIPTION =
    (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.6.190)(PORT = 1521))
    (CONNECT_DATA =
      (SERVER = DEDICATED)
      (SERVICE_NAME = dg2)
    )
  )


三、创建standby数据库

主库只需要复制密码文件 $ORACLE_HOME/dbs/orapwdg1 到 windows $ORACLE_HOME/database/目录下 改名为orapwdg2

如果是异机需要   在d:\app\administrator\admin\asm11g\目录下 新建adump,dpdump,pfile 三个目录   -----本次实验是同一台机器就不建了

 

创建备库instance

windows平台利用oradim工具创建一个新的instance,unix/linux平台设置新的ORACLE_SID即可,我的是linux平台,设置ORACLE_SID即可。

C:\Documents and Settings\Administrator>oradim -new -sid dg2   ----删除可用oradim -delete -sid dg2
实例已创建。

新建pfile文件
dg2.DB_NAME=dg1
dg2.DB_UNIQUE_NAME=dg2
*.audit_file_dest='D:\oracle\admin\dg2\adump'
*.control_files='G:\Oracle\oradata\DG2\DATAFILE\control01.ctl','G:\Oracle\oradata\DG2\DATAFILE\control02.ctl'
*.db_block_size=8192
*.db_recovery_file_dest='G:\Oracle\arch'
*.db_recovery_file_dest_size=10G 


启动数据库到nomount状态

SQL> startup nomount pfile='D:\oracle\product\11.2.0\dbhome_1\database\initdg2.ora';


四、  执行duplicate 复制standby库
 set ORACLE_SID=dg2
 
[oracle@db1 dbs]$ rman target sys/oracle@dg1 auxiliarysys/oracle@dg2

RMAN> run {
allocate channel prmy1 type disk;
allocate channel prmy2 type disk;
allocate channel prmy3 type disk;
allocate channel prmy4 type disk;
allocate auxiliary channel stby type disk;

duplicate target database for standby from active database
spfile
  parameter_value_convert 'dg1','dg2'
  set db_unique_name='dg2'
  set db_file_name_convert='D:\ORACLE\ORADATA\DG1\DATAFILE\','G:\Oracle\oradata\DG2\DATAFILE\'
  set log_file_name_convert='D:\oracle\arch','G:\oracle\arch'
  set control_files='G:\Oracle\oradata\DG2\DATAFILE\control01.ctl','G:\Oracle\oradata\DG2\DATAFILE\control02.ctl'
  set log_archive_max_processes='5'
  set fal_client='dg2'
  set fal_server='dg1'
  set standby_file_management='AUTO'
  set log_archive_config='dg_config=(dg1,dg2)'
  set log_archive_dest_1='location=G:\Oracle\arch VALID_FOR=(ALL_LOGFILES,ALL_ROLES) DB_UNIQUE_NAME=dg2'
  set log_archive_dest_2='service=dg1 ASYNC valid_for=(ONLINE_LOGFILE,PRIMARY_ROLE) db_unique_name=dg1'
;
}

五、standby数据库,开启dataguard
SQL> alter database mount standby database; 

数据库已更改。

将备库置于自动恢复状态

SQL>  alter database recover managed standby database disconnect from session;

数据库已更改。

六、对于active dataguard,可以再使用如下命令

停止日志应用:
SQL> alter database recover managed standby database cancel;

数据库已更改。

SQL> alter database open;

数据库已更改。

置于恢复状态:
SQL> alter database recover managed standby database disconnect;

数据库已更改。

开启物理standby的日志实时应用(从库):
SQL> alter database recover managed standby database using current logfile disconnect from session;

数据库已更改。

注:
(1)
------此处需要手动编辑sid列,静态监听,否则报错RMAN-00554: 内部恢复管理器程序包初始化失败
RMAN-04005: 目标数据库中存在错误:
ORA-12514: TNS: 监听程序当前无法识别连接描述符中请求的服务
standby监听器必须是静态监听

(2)db_file_name_convert要正确设置,否者会报错ORA-17628, ORA-19505

 


验证:
分别在主备库执行
SQL> select max(sequence#) from v$archived_log;

MAX(SEQUENCE#)
--------------
             9

            
查看数据库角色和数据保护模式:
select protection_mode,database_role,protection_level from v$database;

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

主变从:
select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
TO STANDBY --可以直接切换

alter database commit to switchover to physical standby;

SWITCHOVER_STATUS
--------------------
SESSIONS ACTIVE --不能直接切换执行下列命令

alter database commit to switchover to physical standby with session shutdown;

切换过程:
SQL> alter database commit to switchover to physical standby with session shutdown;

数据库已更改。

SQL> shut immediate
ORA-01507: 未装载数据库


ORACLE 例程已经关闭。
SQL> startup nomount;
ORACLE 例程已经启动。

Total System Global Area  535662592 bytes
Fixed Size                  1375792 bytes
Variable Size             243270096 bytes
Database Buffers          285212672 bytes
Redo Buffers                5804032 bytes
SQL> alter database mount standby database;

数据库已更改。

------------------------------------------------------------------------------------------------------
从变主:
select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
NOT ALLOWED --没有切换标记!不能切换
TO PRIMARY --可以直接切换


ALTER DATABASE RECOVER MANAGED STANDBY DATABASE;
 select switchover_status from v$database;

操作时遇到的问题:
SQL> select switchover_status from v$database;    ---第一次切换查看状态是NOT ALLOWED

SWITCHOVER_STATUS
--------------------
NOT ALLOWED

SQL> alter database recover managed standby database cancel;   ---执行切换报错

数据库已更改。

SQL> alter database commit to switchover to primary;
alter database commit to switchover to primary
*
第 1 行出现错误:
ORA-16139: 需要介质恢复

 

SQL> select sequence#, applied from v$archived_log;  ---查看归档,有没应用的(no 状态)

 SEQUENCE# APPLIED
---------- ---------
         6 YES
         7 YES
         9 YES
        10 YES
        11 YES
        12 YES
        13 YES
         8 YES
        14 YES
        16 YES
        15 YES

 SEQUENCE# APPLIED
---------- ---------
        17 YES
        18 YES
        19 YES
        20 NO
        21 NO
        22 NO
       
       
SQL> alter database recover managed standby database finish force;     ---failover 使用

数据库已更改。

SQL> select sequence#, applied from v$archived_log;

 SEQUENCE# APPLIED
---------- ---------
         6 YES
         7 YES
         9 YES
        10 YES
        11 YES
        12 YES
        13 YES
         8 YES
        14 YES
        16 YES
        15 YES

 SEQUENCE# APPLIED
---------- ---------
        17 YES
        18 YES
        19 YES
        20 YES
        21 YES
        22 YES

已选择17行。

SQL> select switchover_status from v$database;

SWITCHOVER_STATUS
--------------------
TO PRIMARY

--归档也应用了,状态也改变了

SQL> alter database commit to switchover to primary; 

数据库已更改。

--成功切换

SQL> select protection_mode,database_role,protection_level from v$database;

PROTECTION_MODE      DATABASE_ROLE    PROTECTION_LEVEL
-------------------- ---------------- --------------------
MAXIMUM PERFORMANCE  PRIMARY          UNPROTECTED

SQL> alter database open;

数据库已更改。

在主库中查看第二存档终点是否有异常:
col dest_name for a30
col error for a20
select dest_name,status,error,target,process from v$archive_dest where substr(dest_name,-1) in (1,2);

 

注:
误在dg备库上执行了:
alter database recover managed standby database finish;(只有在failover时使用)
导致无法归档,上述语句只有在failover情况下使用,用来保障数据安全,之后备库要以primary启动。

报错:ORA-16143:终端恢复过程中或之后不允许进行 RFS 连接

恢复方法:
1.重建备库(所有问题的统一解决方法^_^)
2.从主库重建一份控制文件
然后覆盖备系统控制文件。
重新启动备库,ok。

 

--------------------------------------------------------------------------------------------------------------------------------
最高可用的物理standby

主库日志传输模式级别要更细致:
redo条目级别         网络同步         i/o同步
LGWR                    SYNC             AFFIRM

SQL> alter system set log_archive_dest_2='SERVICE=dg1 LGWR ASYNC affirm VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=dg1';
在最大可用的物理standby要拥有自己的联机日志:接收主库传送过来的redo条目
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo05.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo06.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo07.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo08.log' size 50m;

从库要拥有归档路径:
当数据库角色为standby,联机日志类型为standby时使用log_archive_dest_3指向的路径保存归档
alter system set log_archive_dest_3='location=D:\oracle\oradata\DG1\arch\ valid_for=(STANDBY_LOGFILES,STANDBY_ROLE) db_unique_name=dg1';

将数据库转换为最高可用模式(主库):
shutdown immediate
startup mount
alter database set standby database to maximize availability;
alter database open;

查看数据库保护模式:
select protection_mode,database_role,protection_level from v$database;

 

--------------------------------------------------------------------------------------------------------
在Oracle 11g里,Data Guard 切换多了一个新的功能:flush redo。
Flush 能把没有发送的redo 从主库传送到standby库。
只要主库能启动到mount 状态,那么Flush 就可以把没有发送的归档和current online redo 发送到备库。
Flush语法:
       SQL> ALTER SYSTEM FLUSH REDO TO 'target_db_name';

这里的target_db_name 是我们在备库的db_unique_name 名称。  Flush 会将未发送的redo 从主库传到备库,并且等待redo在standby 库上apply 之后返回成功。 所以只要Flush成功,那么Failover 就没有数据丢失。


--------------------------------------------------------------------------------------------------------
准备转换角色:(由物理到逻辑)
从库中停止管理恢复进程
ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

在主库中创建logical standby需要的数据字典
EXECUTE DBMS_LOGSTDBY.BUILD; --可能会01555

主库做一次归档,使字典信息能传送到从库
alter system switch logfile;
--alter system archive log current;

备库执行:
物理standby转逻辑standby:
alter database recover to logical standby db_name; --指定数据库名称,可以和主库不同

重新启动从库(resetlogs)
shutdown immediate
startup mount
alter database open resetlogs;

启动sql apply
alter database start logical standby apply;

为从库添加standby redo logfile
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo05.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo06.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo07.log' size 50m;
alter database add standby logfile 'D:\ORACLE\ORADATA\DG2\ONLINELOG\redo08.log' size 50m;

启动real time sql apply(日志实时应用)
alter database stop logical standby apply;
alter database start logical standby apply immediate;

查看逻辑standby操作日志:(只保留100条操作)
select event_time,status,event from dba_logstdby_events;

查看日志应用情况:
select sequence#,first_change#,next_change#,timestamp,applied from dba_logstdby_log;

停止sql应用:
alter database stop logical standbyapply;

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

监控逻辑standby

 
    与物理standby 的管理一样,oracle 提供了一系列动态性能视图来查看逻辑standby 的状态,有一些我们前面已经接触过,而有一些,我们还从未用过。
 
1、DBA_LOGSTDBY_EVENTS

 
    可以把该视图看成逻辑standby 操作日志,因此如果发生了错误,可以通过该视图查看近期逻辑standby都做了些什么。默认情况下, 该视图保留100 条事件的记录, 不过你可以通过DBMS_LOGSTDBY.APPLY_SET()过程修改该参数。

 
    例如:

    JSSLDG2> select event_time,status,event from dba_logstdby_events;
    EVENT_TIME          STATUS                                    EVENT
    ------------------- ----------------------------------------- ----------------------------------------
    2008-03-06 08:58:11 ORA-16112: 日志挖掘和应用正在停止
    2008-03-06 09:02:00 ORA-16111: 日志挖掘和应用正在启动
    2008-03-06 09:52:53 ORA-16128: 已成功完成用户启动的停止应用操作
    2008-03-12 15:52:53 ORA-16111: 日志挖掘和应用正在启动
    2008-03-12 16:09:17 ORA-16226: 由于不支持而跳过DDL              ALTER DATABASEOPEN
    2008-03-05 17:21:46 ORA-16111: 日志挖掘和应用正在启动
    ..............................

2、DBA_LOGSTDBY_LOG

 
    该视图用来记录当前的归档日志应用情况,等同于物理standby 中的v$archived_log,多数情况下,你只需要关注SEQUENCE#,APPLIED,即查看日志序号和是否应用,当然该视图还能提供更多信息,比如应用的scn,应用时间等,例如:

    JSSLDG2> select sequence#,first_change#,next_change#,timestamp,applied from dba_logstdby_log;
    SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# TIMESTAMP           APPLIED
    ---------- ------------- ------------ ------------------- --------
    869        1319212       1319811      2008-03-12 16:09:15 CURRENT

    通常情况下,该查询只会返回几条记录,如果说你的数据库操作非常频繁,可能记录数会稍多一些,但如果记录数非常多,那你可能就需要关注一下,是不是出了什么问题,难道sql 应用没有启动?

 
3、V$LOGSTDBY_STATS

    从名字就大致猜的出来,该视图显示的是状态信息,没错,你猜对了,该视图就是用来显示LogMiner的统计信息及状态。

    JSSLDG2> select *from v$logstdby_stats;
    NAME                                     VALUE
    ---------------------------------------- ---------------
    number of preparers                      1
    number of appliers                       5
    maximum SGA for LCR cache                30
    parallel servers in use                  9
    maximum events recorded                  100
    preserve commit order                    TRUE
    transaction consistency                  FULL
    record skip errors                       Y
    record skip DDL                          Y
    record applied DDL                       N
    .........................

4、V$PROCESV$LOGSTDBY_PROCESS

 
    该视图显示当前log 应用服务的相关信息。常用于诊断归档日志逻辑应用的性能问题(后面优化部分会有涉及),包含的信息也很广:

    ※ 身份信息:SID,SERIAL#,SPID
    ※ SQL 应用进程:COORDINATOR, READER, BUILDER, PREPARER, ANALYZER, 或APPLIER
    ※ 进程当前的状态:见status_code 或status 列
    ※ 该进程当前操作redo 记录最大SCN:high_scn 列

 
    例如:

    JSSLDG2> select sid,serial#,spid,type,status,high_scn from v$logstdby_process;
    SID      SERIAL#   SPID   TYPE            STATUS                                          HIGH_SCN
    -------- ------- -------- --------------- ----------------------------------------------- ----------
    145      1       508      COORDINATOR     ORA-16116: 无可用工作                            1319811
    146      2       2464     READER          ORA-16240: 正在等待日志文件(线程号1,序列号870)     1319811
    143      1       1512     BUILDER         ORA-16116: 无可用工作                            1319742
    142      1       4000     PREPARER        ORA-16116: 无可用工作                            1319741
    139      1       2980     ANALYZER        ORA-16116: 无可用工作                            1319707
    135      1       1648     APPLIER         ORA-16116: 无可用工作                            1319430
    138      1       2332     APPLIER         ORA-16116: 无可用工作                            1319439
    132      1       2200     APPLIER         ORA-16116: 无可用工作                            1319443
    134      1       4020     APPLIER         ORA-16116: 无可用工作
    ...........................................

5、V$PROGRESV$LOGSTDBY_PROGRESS

    该视图显示log 应用服务当前进展状况,比如当前应用到逻辑standby 的scn 及时间,sql 应用开始应用的scn 及时间,最后接收及应用的scn 和时间等等。

    例如:

    JSSLDG2> select * from v$Logstdby_progress;
    APPLIED_SCN APPLIED_TIME        RESTART_SCN RESTART_TIME        LATEST_SCNLATEST_TIME         MINING_SCN MINING_TIME
    ----------- ------------------- ----------- ------------------- ---------- ------------------- ---------- -------------------
    1319810     2008-03-12 16:06:51 1319662     2008-03-12 16:03:22 1319810    2008-03-12 16:45:331319811    2008-03-12 16:06:51

6、V$LOGSTDBY_STATE

    该视图就最简单了,就是显示sql 应用的大致状态,比如primary 库的dbid 啦,是否启动了实时应用啦,当前sql 应用的状态啦之类。

 
    注意state 列,该列可能有下述的几种状态:
    ※ INITIALIZING: LogMiner session 已创建并初始化
    ※ LOADING DICTIONARY: SQL 应用调用LogMiner 字典
    ※ WAITING ON GAP: SQL 应用正等待日志文件,可能有中断
    ※ APPLYING: SQL 应用正在工作
    ※ WAITING FOR DICTIONARY LOGS: SQL 应用等待LogMiner 字典信息
    ※ IDLE: SQL 应用工作非常出色,已经干的没什么可干了:)

 
    例如:

    JSSLDG2> select * from v$Logstdby_state;
    PRIMARY_DBID SESSION_ID REALTIME_APPLY       STATE
    ------------ ---------- -------------------- ----------------------
    3408827880   42         Y                    APPLYING

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

逻辑standby 一个极具实用价值的特性即是可以边查询边应用,因此将其做为报表服务器专供查询是个很不错的想法,而且逻辑standby 相对于物理standby 而言更具灵活性,比如我们可以在逻辑standby上,对一些表创建primary 库上并不方便创建的索引,约束,甚至可以做dml,ddl 操作(当然,需要注意不要破坏了与primary 之间同步的逻辑关系)。不过由于此时dg 仍然控制着对逻辑standby 表的读写操作,因此,如果你想对逻辑standby 中的数据做些什么的话,alter session database disable|enable guard 语句就必须牢记在心了,它拥有像“芝麻开门”一样神奇的能力,不信?下面我们就来感受一下吧。

 
1、逻辑standby端执行ddl

 
    在逻辑standby 端开始了redo 应用的情况下,执行ddl 操作:
    JSSLDG2> create table tmp55 as select * From b;
    create table tmp55 as select * From b
    *
    第1 行出现错误:
    ORA-01031: 权限不足

    看看,出错了吧~~~


    JSSLDG2> alter session disable guard;
    会话已更改。
    JSSLDG2> create table tmp55 as select * From b;
    表已创建。


    只有关闭了guard 保护之后,才能操作数据,然后别忘了再启用guard,以避免不经意的操作对逻辑standby 的配置造成影响。

    JSSLDG2> alter session enable guard;
    会话已更改。

    提示:oracle 建议还是尽可能不要在逻辑standby 执行执行dml 之类操作,以免破解其与primary 之间同步的逻辑关系,当然,这只是个建议,如果你数据库表结构及存储结构了如指掌,那您就爱干嘛干嘛。

 
2、取消对象同步

    如果说,某些表或者数据不需要dataguard 保护(比如一些在逻辑standby 端生成的统计表),这个时候就需要DBMS_LOGSTDBY.SKIP,前头已经介绍过了dbms_logstdby.skip 的基本用法,下面我们来具体演示一下!

    下面我们假设standby 端有一批表名为tmp 开头的表,这张表不再需要保持与primary 的同步,那么按照步骤执行下列语句,sql 应用即可跳过这些表:

 
    老规矩,先停了redo 应用

    JSSLDG2> alter database stop logical standby apply;
    数据库已更改。


    JSSLDG2> executexecute dbms_logstdby.skip('SCHEMA_DDL','JSS','TMP%'); --跳过对象的ddl 操作
    PL/SQL 过程已成功完成。


    JSSLDG2> executedbms_logstdby.skip('DML','JSS','TMP%'); --跳过对象的dml 操作
    PL/SQL 过程已成功完成。


    JSSLDG2> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
    数据库已更改。

 
    注意其中的%,该符号为通配符,作用与在sql 语句中的相同。

 
    OK,下面来测试一下,先看看逻辑standby 中表的信息,我们选择两张表,一张是我们前面已经指定了跳过的表tmp1,另一张是普通表b:

    JSSLDG2> select max(aa) from jss.tmp1;
    Max(aa)
    --------------------
    h


    JSSLDG2> select max(id) from jss.b;
    Max(id)
    ----------
    9


    JSSLDG2> select sequence#,applied from dba_logstdby_log;
    SEQUENCE# APPLIED
    ---------- --------
    872        YES

 
    然后在primary 数据库执行插入操作

    JSSWEB> select max(aa) from jss.tmp1;
    Max(aa)
    --------------------
    h


    JSSWEB> insert into jss.tmp1 values ('i');
    已创建1 行。
    JSSWEB> insert into jss.b values (10);
    已创建1 行。
    JSSWEB> commit;
    提交完成。


    JSSWEB> alter system switch logfile;
    系统已更改。


    JSSWEB> select max(sequence#) from v$archived_log;
    MAX(SEQUENCE#)
    --------------
    873

 
    再来看看逻辑standby 端的同步情况:

    JSSLDG2> select sequence#,applied from dba_logstdby_log;
    SEQUENCE# APPLIED
    ---------- --------
    873        YES

 
    显然日志已经接收,再看看数据:

    JSSLDG2> select max(id) from b;
    Max(id)
    ----------
    10


    JSSLDG2> select max(aa) from jss.tmp1;
    Max(aa)
    --------------------
    h

 
    b 表已应用,而tmp1 表则无变化。

 
3、恢复对象同步

    如果说某些表某个时候取消了同步,现在希望再恢复同步,没问题,DBMS_LOGSTDBY 家大业大,它还有个叫UNSKIP 的门生就是专干这个的。

 
    我们来看一下dbms_logstdby.unskip 的语法:

    DBMS_LOGSTDBY.UNSKIP (
    stmt         IN VARCHAR2,
    schema_name IN VARCHAR2,
    object_name IN VARCHAR2);

 
    三项均为必选参数,各参数的定义与skip 过程相同,这里不再复述。

 
    此处我们来演示恢复tmp%表的同步。
    JSSLDG2> select *from dba_logstdby_skip;
    ERROR STATEMENT_OPT   OWNER      NAME            U E PROC
    ----- --------------- ---------- --------------- - - --------------------
    N     SCHEMA_DDL      JSS        TMP%                Y
    N     DML             JSS        TMP%                Y
    N     DML             JSS        TMP1                Y
    ........


    JSSLDG2> alter database stop logical standby apply;
    数据库已更改。


    JSSLDG2> execute dbms_logstdby.unskip('DML','JSS','TMP1'); --本步操作是为解决历史遗留问题,不用关注
    PL/SQL 过程已成功完成。


    JSSLDG2> executexecute dbms_logstdby.unskip('DML','JSS','TMP%');
    PL/SQL 过程已成功完成。


    JSSLDG2> execute
    dbms_logstdby.unskip('SCHEMA_DDL','JSS','TMP%');
    PL/SQL 过程已成功完成。


    跳过同步已经取消了,紧接着我们需要再调用dbms_logstdby.instantiate_table 过程重新同步一下跳地的对象,将skip 这段时间,primary 对tmp1 表所做的操作同步过来(就俺看来,instantiate_table 过程实际上是借助dblink 重建了一遍对象),以保持与primary 的一致。Dbms_logstdby.instantiate_table 的语法如下:

    DBMS_LOGSTDBY.INSTANTIATE_TABLE (
    schema_name     IN VARCHAR2,
    table_name      IN VARCHAR2,
    dblink          IN VARCHAR2);

    使用DBMS_LOGSTDBY.INSTANTIATE_TABLE 过程重新执行一下同步(执行前别忘了暂停redo 应用):

    JSSLDG2> EXECUTE DBMS_LOGSTDBY.INSTANTIATE_TABLE('JSS','TMP1','GETJSSWEB');
    PL/SQL 过程已成功完成。


    JSSLDG2> select *from jss.tmp1;
    AA
    --------------------
    a
    b
    c
    d
    e
    f
    g
    h
    i
    已选择9 行。

    数据已重建,下面测试一下该表的redo 应用是否恢复了。

    JSSWEB> insert into jss.tmp1 values ('j');
    已创建1 行。
    JSSWEB> insert into jss.tmp1 values ('k');
    已创建1 行。
    JSSWEB> commit;
    提交完成。


    JSSWEB> alter system switch logfile;
    系统已更改。


    JSSWEB> select max(sequence#) from v$archived_log;
    MAX(SEQUENCE#)
    --------------
    877

    启动逻辑standby 端的redo 应用,看看对象的应用情况:

    JSSLDG2> alter database start logical standby apply immediate;
    数据库已更改。


    JSSLDG2> select sequence#,applied from dba_logstdby_log;
    SEQUENCE#  APPLIED
    ---------- --------
    875        YES
    876        YES
    877        YES


    JSSLDG2> select *from jss.tmp1;
    AA
    --------------------
    a
    b
    c
    d
    e
    f
    g
    h
    i
    j
    k
    已选择11 行。

    OK,恢复正常啦!

 
    注意哟,此处我们清楚明白的知道我们之前只操作了tmp1 一张表,如果是正式应用的话,那你恐怕有必要将所有tmp 开头的表都同步一下,不然有可能会造成数据丢失的哟。
 

四、特殊事件的控制

 
1、导入传输表空间

 
    ※ 第一步:屏蔽guard 保护,逻辑standby 端操作

    SQL> ALTER SESSION DISABLE GUARD;

    ※ 第二步:导入传输表空间,逻辑standby 端操作
    具体操作步骤可参考三思之前的笔记:使用可传输表空间的特性复制数据!

 
    ※ 第三步:恢复guard 保护(或者直接退出本session 也成),逻辑standby 端操作

    SQL> ALTER SESSION ENABLE GUARD;

    ※ 第四步:导入传输表空间,primary 端操作
    同第二步。

 
2、使用物化视图

 
    SQL 应用不支持下列对物化视图的ddl 操作:
    ※ create/alter/drop materialized view
    ※ create/alter/drop materialized view log

 
    因此,对于现有逻辑standby,primary 端对物化视图的操作不会传播到standby 端。不过,对于primary创建物化视图之后创建逻辑standby,则物理视图也会存在于逻辑standby 端。

 
    ※ 对于同时存在于primary 和逻辑standby 的ON-COMMIT 物化视图,逻辑standby 会在事务提交时自动刷新,而对于ON-DEMAND 的物化视图不会自动刷新,需要手动调用dbms_mview.refresh 过程刷新。
    ※ 对于逻辑standby 端建立的ON-COMMIT 物化视图会自动维护,ON-DEMAND 物化视图也还是需要手工调用dbms_mview.refresh 过程刷新。

 
3、触发器及约束的运作方式

 
    默认情况下,约束和触发器同样会在逻辑standby 端正常工作。

 
    对于有sql 应用维护的约束和触发器:
    ※ 约束:由于约束在primary 已经检查过,因此standby 端不需要再次检查
    ※ 触发器:primary 端操作时结果被记录,在standby 端直接被应用。

 
    没有sql 应用维护的约束和触发器:
    ※ 约束有效
    ※ 触发器有效

---------------------------------- ---------------------------------- ---------------------------------- -------------------------------
 
优化逻辑standbstandby

 
1、创建PrimaryKeyRELY约束

 
    某些情况下能够有效提高sql 应用效率,具体可参见第三部分第一章。

 
2、生成统计信息

 
    这个很容易理解嘛,因为cbo 要用,生成方式即可用analyze,也可以用dbms_stats 包。看你个人喜好了。

 
3、调整进程数

 
    A).调整APPLIER进程数

 
    首先查看当前空闲的applier 进程数:

    JSSLDG2> SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS
           2 WHERE TYPE = 'APPLIER' and status_code = 16166;
    IDLE_APPLIER
    ------------
    0

    提示:

    status_code = 16166 表示进程是空闲状态,可以看到"STATS"为"ORA-16116: no work available",当然空闲的applier 进程数为0 不一定代表应用应用非常繁忙,也有可能是因为当前没什么需要应用的日志,因此甚至应用进程都没启动:)

    检查事务的应用情况:

    JSSLDG2> select name,value from v$logstdby_stats where name like 'TRANSACTION%';
    NAME                  VALUE
    --------------------- -------
    transactions ready    896
    transactions applied 871

    如果ready-applied 的值比applier 进程数的两倍还要大,则说明你有必要考虑增加applier 进程的数目了,反之如果applied 与ready 的值差不多大,或者其差比applier 进程数还小,则说明applier 进程数偏多,你有必要考虑适当减小进程的数目。
    如果确认当前applier 进程都非常繁忙,要增加applier 进程,可按如下步骤操作:

 
    停止sql 应用

    ALTER DATABASE STOP LOGICAL STANDBY APPLY;

    调整applier 进程数为20,默认是5 个

    EXECUTE DBMS_LOGSTDBY.APPLY_SET('APPLY_SERVERS', 20);

    重启sql 应用

    ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;

    B).调整PREPARER进程数

    需要调整preparer 进程数的机会不多,通常只有一种情况:applier 进程有空闲,transactions ready 还很多,但没有空闲的preparer 进程,这时候你可能需要增加一些preparer 进程。

    要检查系统是否存在这种情况,可以通过下列的sql 语句:

 
    首先检查空闲preparer 进程数量:

    SELECT COUNT(*) AS IDLE_PREPARER FROM V$LOGSTDBY_PROCESS WHERE TYPE ='PREPARER' and status_code = 16166;

    检查事务的应用情况:
    select name,value from v$logstdby_stats where name like 'TRANSACTION%';

 

    查看当前空闲的applier 进程数:

    SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS WHERE TYPE = 'APPLIER'and status_code = 16166;

    如果确实需要调整preparer 进程数量,可以按照下列步骤,例如:

 
    停止sql 应用
    ALTER DATABASE STOP LOGICAL STANDBY APPLY;

 

    调整preparer 进程数量为4(默认只有1 个preparer 进程)
    EXECUTE DBMS_LOGSTDBY.APPLY_SET('PREPARE_SERVERS', 4);

 

    重启sql 应用
    ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;

 

4、调整LCR使用的内存

    执行下列语句,查询当前LCR 可用的最大内存:
    JSSLDG2> select * from v$logstdby_stats where name='maximum SGA for LCR cache';
    NAME                                 VALUE
    ------------------------------------ --------------------
    maximum SGA for LCR cache            30

 
    要增加LCR 可用的内存,按照下列步骤操作:

 
    停止sql 应用:
    JSSLDG2> alter database stop logical standby apply;
    数据库已更改。

    调整内存大小,注意默认单位是M:

    JSSLDG2> execute dbms_logstdby.apply_set('MAX_SGA',100);
    PL/SQL 过程已成功完成。

    重启sql 应用

    JSSLDG2> alter database start logical standby apply immediate;
    数据库已更改。

5、调整事务应用方式

    默认情况下逻辑standby 端事务应用顺序与primary 端提交顺序相同。

 
    如果你希望逻辑standby 端的事务应用不要按照顺序的话,可以按照下列的步骤操作:

    ① 停止 sql 应用 :
    SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;

    ② 允许事务不按照 primary 的提交顺序应用
    SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET('PRESERVE_COMMIT_ORDER', 'FALSE');

    ③ 重新启动 sql 应用
    SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;
 
    恢复逻辑standby 按照事务提交顺序应用的话,按照下列步骤:
    ① 还是先停止 sql 应用:
    SQL> ALTER DATABASE STOP LOGICAL STANDBYAPPLY;

    ② 重置参数 PRESERVE_COMMIT_ORDER 的初始值:
    SQL> EXECUTE DBMS_LOGSTDBY.APPLY_UNSET('PRESERVE_COMMIT_ORDER');

    ③ 重新启动 sql 应用:
    SQL> ALTER DATABASE START LOGICAL STANDBYAPPLY IMMEDIATE;