第三部分逻辑standby(4)高级管理  2008.03.04
								
								
						
				
		
		
				
				 
		
				
						 
				
		
		
				
						
								
										一、监控逻辑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
				
		
		
				
				
						1、接收到的归档文件
				
		
		
				
				
						
								    前章曾经提到,逻辑standby 应用完归档后会自动删除该归档文件,该特性你如果觉着不爽,没关系,执行下面这个过程,屏蔽掉它:
				
		
		
				
						
								
										
												
														    JSSLDG2> EXECUTE DBMS_LOGSTDBY.APPLY_SET('LOG_AUTO_DELETE', FALSE);
										
								
						
				
		 
		
				
						
						
				 
		
				
						
								    提示:这种操作并非毫无意义,比如说逻辑standby 打开了flashback database,那如果你想恢复到之前的某个时间点,然后再接着应用,就必须要有该时间点后对应的归档,假如LOG_AUTO_DELETE 为TRUE的话,显然应用过的归档就不存在了,想回都回不去。
				
		
		
				
				 
		
				
						
								
										2、启动实时应用
								
								
						
				
		
		
				
						
						
				 
		
				
						
								    默认情况下,log 应用服务会等待单个归档文件全部接收之后再启动应用(在前面redo 传输服务中我们介绍了不同形式的传输方式),如果standby 端使用了standby redologs,就可以打开实时应用(real-time apply),这样dg 就不需要再等待接收完归档文件,只要rfs 将redo 数据写入standby redologs,即可通过MRP/LSP
实时写向standby,这样就可以尽可能保持standby 与primary 的同步。
				
		
		
				
						
						
				 
		
				
						
								    要启动逻辑standby 的实时应用,只需要在启动逻辑standby 应用时加上immediate 子句即可,前面我们已经无数次的演练过,例如:
						
								
										
												    JSSLDG2> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
								
						
				
		 
		
				
				 
		
				
						
								
										3、定义DBA_EVENTDBA_LOGSTDBY_EVENTS视图中事件记录的相关参数。
								
								
						
				
		
		
				
						
						
				 
		
				
						
								    Dba_logstdby_events 视图前面刚讲过,里面记录了逻辑standby 的一些操作事件,如果你希望修改该视图中记录的事件信息的话,可以通过下列的方式:
				
		
		
				
						
						
				 
		
				
						
								    例如,希望该视图能够保留最近999 条事件,可以通过执行下列语句:
				
				
						
								
										    JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
    NAME                                         VALUE
    -------------------------------------------- ---------------
    maximum events recorded                      100
						
				
				
						
								
										    JSSLDG2> alter database stop logical standby apply;
    数据库已更改。
						
				
				
						
								
										    JSSLDG2> execute dbms_logstdby.apply_set('max_events_recorded','999');
    PL/SQL 过程已成功完成。
						
				
				
						
								
										    JSSLDG2> alter database start logical standby apply immediate;
    数据库已更改。
						
				
				
						
								
										    JSSLDG2> select *from v$logstdby_stats where name='maximum events recorded';
								
										
												    NAME                                         VALUE
    -------------------------------------------- ---------------
										
										    maximum events recorded                      999
						
				
		 
		
				
						 
				
		
		
				
						
								    再比如,你如果想在视图中记录ddl 操作的信息,可以通过执行下列语句:
				
		
		
				
						
								    JSSLDG2> execute dbms_logstdby.apply_set('RECORD_APPLIED_DDL','TRUE');
				
		
		
				
						 
				
		
		
				
						4、指定对象跳过应用,请用DBMS_LOGSTDBY.SKIP
				
		
		
				
				
						
								    默认情况下,接收自primary 的redo 数据中,所有能够被standby 支持的操作都会在逻辑standby 端执行,如果你希望跳过对某些对象的某些操作的话,DBMS_LOGSTDBY.SKIP 就能被派上用场了。
				
		
		
				
						
						
				 
		
				
						
								    先来看看dbms_logstdby.skip 的语法:
    DBMS_LOGSTDBY.SKIP (
    stmt            IN VARCHAR2,
    schema_name     IN VARCHAR2 DEFAULT NULL,
    object_name     IN VARCHAR2 DEFAULT NULL,
    proc_name       IN VARCHAR2 DEFAULT NULL,
    use_like        IN BOOLEAN DEFAULT TRUE,
    esc             IN CHAR1 DEFAULT NULL);
				
		
		
				
						
								    除stmt 外,其它都是可选参数,并且看字面意义就能明白其所指,下面简单描述一下stmt 参数调用的关键字都是指定值,详细见下列:
				
				
						
						 
				
		
		
				
				
				
						
								
										
												
												
										
								
								
										
												| STMT关键字 | 包含的操作 | 
										
												| NON_SCHEMA_DDL | 不属于模式对象的所有其它ddl操作 | 
										
												| 提示:使用该关键字时,SCHEMA_NAME和OBJECT_NAME两参数也必须指定。 | 
										
												| SCHEMA_DDL | 创建修改删除模式对象的所有ddl操作(例如: tables, indexes, and columns) | 
										
												| 提示:使用该关键字时,SCHEMA_NAME和OBJECT_NAME两参数也必须指定。 | 
										
												| DML | Includes DML statements on a table (for example: INSERT, UPDATE, and DELETE) | 
										
												| CLUSTER | AUDIT CLUSTER | 
										
												| CREATE CLUSTER | 
										
												| DROP CLUSTER | 
										
												| TRUNCATE CLUSTER | 
										
												| CONTEXT | CREATE CONTEXT | 
										
												| DROP CONTEXT | 
										
												| DATABASE LINK | CREATE DATABASE LINK | 
										
												| CREATE PUBLIC DATABASE LINK | 
										
												| DROP DATABASE LINK | 
										
												| DROP PUBLIC DATABASE LINK | 
										
												| DIMENSION | ALTER DIMENSION | 
										
												| CREATE DIMENSION | 
										
												| DROP DIMENSION | 
										
												| DIRECTORY | CREATE DIRECTORY | 
										
												| DROP DIRECTORY | 
										
												| INDEX | ALTER INDEX | 
										
												| CREATE INDEX | 
										
												| DROP INDEX | 
										
												| PROCEDURE | ALTER FUNCTION | 
										
												| ALTER PACKAGE | 
										
												| ALTER PACKAGE BODY | 
										
												| ALTER PROCEDURE | 
										
												| CREATE FUNCTION | 
										
												| CREATE LIBRARY | 
										
												| CREATE PACKAGE | 
										
												| CREATE PACKAGE BODY | 
										
												| CREATE PROCEDURE | 
										
												| DROP FUNCTION | 
										
												| DROP LIBRARY | 
										
												| DROP PACKAGE | 
										
												| DROP PACKAGE BODY | 
										
												| DROP PROCEDURE | 
										
												| PROFILE | ALTER PROFILE | 
										
												| CREATE PROFILE | 
										
												| DROP PROFILE | 
										
												| ROLE | ALTER ROLE | 
										
												| CREATE ROLE | 
										
												| DROP ROLE | 
										
												| SET ROLE | 
										
												| ROLLBACK STATEMENT | ALTER ROLLBACK SEGMENT | 
										
												| CREATE ROLLBACK SEGMENT | 
										
												| DROP ROLLBACK SEGMENT | 
										
												| SEQUENCE | ALTER SEQUENCE | 
										
												| CREATE SEQUENCE | 
										
												| DROP SEQUENCE | 
										
												| SYNONYM | CREATE PUBLIC SYNONYM | 
										
												| CREATE SYNONYM | 
										
												| DROP PUBLIC SYNONYM | 
										
												| DROP SYNONYM | 
										
												| TABLE | ALTER TABLE | 
										
												| CREATE TABLE | 
										
												| DROP TABLE | 
										
												| TABLESPACE | CREATE TABLESPACE | 
										
												| DROP TABLESPACE | 
										
												| TRUNCATE TABLESPACE | 
										
												| TRIGGER | ALTER TRIGGER | 
										
												| CREATE TRIGGER | 
										
												| DISABLE ALL TRIGGERS | 
										
												| DISABLE TRIGGER | 
										
												| DROP TRIGGER | 
										
												| ENABLE ALL TRIGGERS | 
										
												| ENABLE TRIGGER | 
										
												| TYPE | ALTER TYPE | 
										
												| ALTER TYPE BODY | 
										
												| CREATE TYPE | 
										
												| CREATE TYPE BODY | 
										
												| DROP TYPE | 
										
												| DROP TYPE BODY | 
										
												| USER | ALTER USER | 
										
												| CREATE USER | 
										
												| DROP USER | 
										
												| VIEW | CREATE VIEW | 
										
												| DROP VIEW | 
								
						
				
		 
		
				
				 
		
				
						
								    例如,你想跳过jss 用户下对tmp1 表的dml 操作,可以通过执行下列语句实现(执行该过程前需要先停止redo 应用):
				
		
		
				
						
								
										    JSSLDG2> alter database stop logical standby apply;
    数据库已更改。
						
				
				
						
								
										    JSSLDG2> executedbms_logstdby.skip('DML','JSS','TMP1');
    PL/SQL 过程已成功完成。
						
				
				
						
								
										    JSSLDG2> alter database start logical standby apply;
    数据库已更改。
						
				
		 
		
				
				
				
				
						
								    提示:DBMS_LOGSTDBY.SKIP 的功能非常强大,限于篇幅,这里仅举示例,而且由于其操作非常灵活,此篇俺也不可能就其用法做个一一列举,因此,更丰富的操作方式就留待看官们下头自行发现去吧:)
				
		
		
				
				 
		
		
		
				
				
						三、修改逻辑standby端数据
				
		
		
				
				
						
								    我们前面提到,逻辑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 之间同步的逻辑关系,当然,这只是个建议,如果你已经仔细看完了3.1 章,并且对数据库表结构及存储结构了如指掌,那您就爱干嘛爱嘛。
				
		
		
				
						
						
				 
		
				
						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;