一. 确认操作的对象和语句是否能被逻辑Standby支持

1.1 由于逻辑Standby是通过SQL应用来保持与Primary数据库的同步。SQL应用与REDO应用是有很大的区别,REDO应用实际上是在物理Standby端进行RECOVER;SQL应用则是分析重做日志文件中的REDO信息,并将其转换为SQL语句,在逻辑Standby端执行,因此,需要注意以下几点:

(1)并非所有的数据类型都能被逻辑Standby支持,
逻辑Standby支持的数据类型有:
BINARY_DOUBLE、BINARY_FLOAT、BLOB、CHAR、CLOB and NCLOB、 DATE、INTERVAL YEAR TO MONTH、INTERVAL DAY TO SECOND、 LONG、LONG RAW、NCHAR、NUMBER、NVARCHAR2、RAW、TIMESTAMP、
TIMESTAMP WITH LOCAL TIMEZONE、TIMESTAMP WITH TIMEZONE、VARCHAR2 and VARCHAR

说明:下列类型在获取Standby支持时需要注意兼容性:
CLOB,需要Primary数据库的兼容级别运行于10.1或更高。
含LOB字段的索引组织表(IOT),需要Primary数据库的兼容级别运行于10.2或更高。
不含LOB字段的索引组织表(IOT),需要Primary数据库的兼容级别运行于10.1或更高。

不支持的数据类型有:
BFILE、Encrypted Columns、ROWID, UROWID、XMLType、对象类型、VARRAYS、嵌套表、自定义类型。

也可以通过查询DBA_LOGSTDBY_UNSUPPORTED来确定主数据库中是否含有不支持的对象
SQL> select * from dba_logstdby_unsupported;
注意:该视图的ATTRIBUTES列,显示对象不被SQL应用支持的原因。

(2)并非所有的存储类型都能被逻辑Standby支持。
逻辑Standby能够支持簇表(Cluster Tables)、索引组织表(Index-Organized Tables)、堆组织表(Heap-Organized Tables),但不支持段压缩(Segment Compression)存储类型。

(3)并非所有的PL/SQL包都能被SQL应用支持。
通常那些不会修改系统元数据(Metadata)的Package在实际应用时不会有问题,如DBMS_OUTPUT、DBMS_RANDOM、DBMS_METADATA之类的包。
那些可能修改系统元数据的Package不会被SQL应用支持,即使它们在Primary执行过,并且被成功传输到逻辑Standby端,也不会执行。如DBMS_JAVA、DBMS_REGISTRY、DBMS_ALERT、DBMS_SPACE_ADMIN、DBMS_REFRESH、DBMS_REDEFINITION、DBMS_SCHEDULER及DBMS_AQ等。只有DBMS_JOB例外,Primary数据库的jobs会被复制到逻辑Standby,不过在逻辑Standby数据库不会执行这些job。

说明:元数据,直接理解成对象的物理定义。举例来说,对于某表而言,元数据就是表结构,或表的存储属性等。

(4)并非所有的SQL语句都能在逻辑Standby端执行。
在默认情况下,下列SQL语句在逻辑Standby端会被SQL应用自动跳过:
ALTER DATABASE。
ALTER MATERIALIZED VIEW。
ALTER MATERIALIZED VIEW LOG。
ALTER SESSION。
ALTER SYSTEM。
CREATE CONTROL FILE。
CREATE DATABASE。
CREATE DATABASE LINK。
CREATE PFILE FROM SPFILE。
CREATE MATERIALIZED VIEW。
CREATE MATERIALIZED VIEW LOG。
CREATE SCHEMA AUTHORIZATION。
CREATE SPFILE FROM PFILE。
DROP DATABASE LINK。
DROP MATERIALIZED VIEW。
DROP MATERIALIZED VIEW LOG。
EXPLAIN。
LOCK TABLE。
SET CONSTRAINTS。
SET ROLE。
SET TRANSACTION。

另外,由于SQL语句非常灵活,即使是那些能被SQL应用支持的DDL语句,可能在附加了某些特别的参数后,也不会在逻辑Standby端执行,由于数目较多,此处不再一一列举,感兴趣的话请查阅官方文档。

(5)并非所有的DML操作都能在逻辑Standby端实面SQL应用。
维护逻辑Standby与Primary的数据库同步是通过SQL应用实现,SQL应用转换的SQL语句在执行时,对于INSERT还好说,对于UPDATE、DELETE操作则必须能够唯一定位到数据库待更新的那条记录。问题就在这里,如果Primary库中表设置不当,可能就无法确认唯一条件。
你可能会说可以通过ROWID唯一嘛!千万要谨记啊,逻辑Standby,为啥叫逻辑Standby,就是因为它只是逻辑上与Primary数据库相同,物理上可能与Primary数据库存在相当大差异。一定要认识到,逻辑Standby的物理结构与Primary是不相同的(即使初始逻辑Standby是通过Primary的备份创建)。
因此想通过ROWID更新显然是不好使的,当然也就不能再将其作为唯一条件。下面来看这个问题。

1.2 确保Primary库中各表的行可被唯一标识
Oracle通过主键、唯一索引/约束的补充日志(Supplemental Logging)来确定待更新逻辑Standby数据库中的行。当数据库启用了补充日志,每一条UPDATE语句写REDO的时候会附加列值唯一信息,比如:
如果表定义了主键,则主键列会随同被更新列一起作为UPDATE语句的一部分,以便执行时区分哪些列应该被更新。
如果没有主键,则非空的唯一索引/约束会随同被更新列作为UPDATE语句的一部分,以便执行时区分哪些列应该被更新,如果该表有多个唯一索引/约束,则Oracle自动选择长度最短的那个,以降低生成的重做日志大小。
如果表既无主键,也没有定义唯一索引/约束,所有可定长度的列,连同被更新列同时作为UPDATE语句的一部分。更明确些,可定长度的列是指除LONG、LOB、LONG RAW、OBJECT TYPE、COLLECTION类型外的列。
Oracle 建议你为表创建一个主键或非空的唯一索引/约束,以尽可能确保SQL应用能够有效应用REDO数据,更新逻辑Standby数据库。

下列语句可以用来检查SQL应用能否唯一识别表列,并找出不被支持的表:
SQL> SELECT OWNER, TABLE_NAME FROM DBA_LOGSTDBY_NOT_UNIQUE WHERE (OWNER, TABLE_N
AME) NOT IN (SELECT DISTINCT OWNER, TABLE_NAME FROM DBA_LOGSTDBY_UNSUPPORTED)
AND BAD_COLUMN = ‘Y’;

OWNER TABLE_NAME
—– —————
TSMSY SRS$

提 示: 关于DBA_LOGSTDBY_NOT_UNIQUE, 该视图显示所有既没主键也没唯一索引的表。如果表中的列包括足够多的信息,通常也可支持在逻辑Standby端的更新,不被支持的表通常是由于列的定义包含了不支持的数据类型。

注意BAD_COLUMN列值,该列有两个值:
Y:表示该表中有采用大数据类型的字段,比如LONG、CLOB。如果表中除LOG列某些行记录完全匹配,则该表无法成功应用于逻辑Standby。Standby会尝试维护这些表,不过你必须保证应用不允许。
N:表示该表拥有足够的信息,能够支持在逻辑Standby的更新,不过仍然建议你为该表创建一个主键或者唯一索引/约束,以提高LOG应用效率。

假设在某张表中你可以确认数据是唯一的,但是基于效率方面的考虑,不想为其创建主键或唯一约束,怎么办呢?没关系,Oracle早想到了这一点,你可以创建一个DISABLE的Primary-Key Rely约束:

提 示: 关于Primary-Key Rely约束。
如果DBA能够确认表中的行是唯一的,那么可以为该表创建Rely的主键,Rely约束并不会造成系统维护主键的开销,如你对一个表创建了RELY约束,系统则会假定该表中的行是唯一的,这样能够提高SQL应用时的性能。但是需要注意,由于Rely的主键约束只是假定唯一,如果实际并不唯一的话,有可能会造成错误的更新哟。
创建Rely的主键约束非常简单,只要在标准的创建语句后加上RELY DISABLE即可,例如:
SQL> ALTER TABLE USER ADD PRIMARY KEY (ID) RELY DISABLE;
表已更改。

注 意: 创建了Rely约束后,Oracle会假定该列是唯一的(给DBA足够的信任),不过并不会对该列的值进行唯一性的验证,因此该列是否唯一只能由DBA来主动维护。

二. 管理逻辑Standby的相关视图
1.DBA_LOGSTDBY_EVENTS
可以把该视图看成逻辑Standby操作日志,因此如果发生了错误,可以通过该视图查看近期逻辑Standby都做了些什么。默认情况下,该视图只保留最近100条事件的记录(可以通过相关过程修改保存的记录条数)。
例如:
SQL> SELECT EVENT_TIME,STATUS,EVENT FROM DBA_LOGSTDBY_EVENTS
ORDER BY EVENT_TIMESTAMP;
EVENT_TIM STATUS EVENT
——— ————————————————– ——————-
05-MAY-10 ORA-16111: log mining and apply setting up
05-MAY-10 ORA-16257: Switchover initiated stop apply success

2.DBA_LOGSTDBY_LOG
该视图用来记录当前的重做日志的应用情况,功能类似于物理Standby中的V$ARCHIVED_LOG。
多数情况下,你只需要关注SEQUENCE#、APPLIED等有限的几个列,即查看日志序号和是否应用,当然该视图还能提供更多信息,如应用的SCN、应用时间等,例如:
SQL> SELECT SEQUENCE#,FIRST_CHANGE#,NEXT_CHANGE#,
TIMESTAMP,APPLIED FROM DBA_LOGSTDBY_LOG;
SEQUENCE# FIRST_CHANGE# NEXT_CHANGE# TIMESTAMP APPLIED
———- ————- ———— ——— ——–
110 572160 572171 05-MAY-10 CURRENT
111 572171 572175 05-MAY-10 NO

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

3.V$LOGSTDBY_STATS
该视图就是用来显示LogMiner的状态等相关信息,例如:
SQL> 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
record unsupported operations N

4.V$LOGSTDBY_PROCESS
该视图显示当前日志应用服务的相关信息。常用于诊断归档日志逻辑应用的性能问题(后面优化部分会涉及),包含的信息也很广,包括:
身份信息:SID、SERIAL#、SPID。
SQL应用进程:COORDINATOR、READER、BUILDER、PREPARER、ANALYZER、或APPLIER。
进程当前的状态:见STATUS_CODE或STATUS列。
该进程当前操作REDO记录最大SCN:HIGH_SCN列。
例如:
SQL> SELECT SID,SERIAL#,SPID,TYPE,STATUS,HIGH_SCN FROM V$LOGSTDBY_PROCESS;
SID SERIAL# SPID TYPE STATUS
———- ———- ———— ————— —————————–
139 303 6831 COORDINATOR ORA-16116: no work available
153 292 6833 READER ORA-16240: Waiting for logfil
136 5 6835 BUILDER ORA-16116: no work available
137 5 6837 PREPARER ORA-16116: no work available
128 1 6841 ANALYZER ORA-16116: no work available
132 1 6843 APPLIER ORA-16116: no work available
133 2 6845 APPLIER ORA-16116: no work available
130 1 6847 APPLIER ORA-16116: no work available
129 1 6849 APPLIER ORA-16116: no work available
131 1 6851 APPLIER ORA-16116: no work available

5.V$LOGSTDBY_PROGRESS
该视图显示LOG应用服务当前进展状况,如当前应用到逻辑Standby的SCN及时间,SQL应用开始应用的SCN及时间,最后接收及应用的SCN和时间等。

例如,查看当前应用的SCN信息:
SQL> SELECT APPLIED_SCN, LATEST_SCN, MINING_SCN, RESTART_SCN FROM V$LOGSTDBY_PROGRESS;

APPLIED_SCN LATEST_SCN MINING_SCN RESTART_SCN
———– ———- ———- ———–
572164 572232 572166

6.V$LOGSTDBY_STATE
该视图显示SQL应用的大致状态,如Primary数据库的DBID,是否实时应用,当前SQL应用的状态。需要注意的是该视图的STATE列,该列可能有下述的几种状态。应用日志的过程,也是这几种状态相互转换的过程。

1) INITIALIZING初始化状态。
执行ALTER DATABASE START LOGICAL STANDBY APPLY语句,启动SQL应用时,首先就会进入初始化状态,例如:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.
SQL> SELECT SESSION_ID, STATE FROM V$LOGSTDBY_STATE;
SESSION_ID STATE
———- ——————————
21 INITIALIZING
这个状态存在的时间非常短暂,多数情况下只有当ALTER DATABASE START LOGICAL STANDBY APPLY执行时查看V$LOGSTDBY_STATE视图,会看到初始化状态,一旦该命令执行完,状态就被切换为等待字典日志或应用中的状态了。

2) WAITING FOR DICTIONARY LOGS等待数据字典日志。
指第一次初始化时的状态,如刚从物理Standby转换成逻辑Standby,需要首先应用来自Primary端生成的数据字典,在等待Primary数据字典信息时,就会处于这一状态。例如:
SQL> SELECT SESSION_ID, STATE FROM V$LOGSTDBY_STATE;
SESSION_ID STATE
———- ——————————
21 WAITING FOR DICTIONARY LOGS
这个过程也非常短暂。

3) LOADING DICTIONARY加载并分析。
当查询V$LOGSTDBY_STATE视图,显示下列状态时,说明处于加载数据字典的状态:
SQL> SELECT SESSION_ID, STATE FROM V$LOGSTDBY_STATE;
SESSION_ID STATE
———- ——————————
21 LOADING DICTIONARY

对于比较大型的数据库系统,加载数据字典需要一些时间。此时还可以查询V$lOGMNR_DICTIONARY_LOAD视图获取关于加载的更详细的信息,例如:

SQL>SELECT PERCENT_DONE, COMMAND FROM V$LOGMNR_DICTIONARY_LOAD
WHERE SESSION_ID =(SELECT SESSION_ID FROM V$LOGSTDBY_STATE);
APPLYING应用REDO数据。
SQL应用正在处理中,如果要查看当前的处理进度,可以通过V$LOGSTDBY_PROGRESS视图完成。

4) WAITING ON GAP中断等待状态。
SQL应用挖掘并应用了所有可用的REDO数据,正等待新的日志文件,也有可能是由于归档文件有中断造成的。如果查询V$LOGSTDBY_STATE视图时发现处于这一状态,应该同时查询V$ARCHIVE_GAP视图,检查是否有中断的归档。

5) IDLE空闲状态。
处于这一状态也有可能不是好现象,一方面可能是逻辑Standby处理能力优秀,所有活都干完了;也可能是Primary数据库发送日志或逻辑Standby日志出现了问题,导致SQL应用无活可干,因此处于空闲状态。
如果你发现你的逻辑Standby数据库长期处于这一状态,建议查询DBA_LOGSTDBY_LOG视图,确认Primary端产生的日志文件能被逻辑Standby数据库正常接收。

6) SQL APPLY NOT ON。
如果你查询V$LOGSTDBY_STATE视图时发现提示这一状态,说明逻辑Standby数据库根本没启动SQL应用。

三.逻辑Standby数据库的自定义配置
3.1 取消自动删除归档文件
逻辑Standby应用完归档后会自动删除该归档文件,这一极具体贴意味的特性,是由逻辑Standby中的一项参数控制的,如果希望禁用自动删除的功能,可以执行下列语句:
SQL> EXEC DBMS_LOGSTDBY.APPLY_SET(‘LOG_AUTO_DELETE’, ‘FALSE’);
PL/SQL procedure successfully completed.

在某些情况下确实需要禁用归档文件的自动删除功能,如逻辑Standby需要执行Flashback Database操作,如果你想恢复到之前的某个时间点,然后再接着应用,就必须要有该时间点后对应的归档,假如LOG_AUTO_DELETE为TRUE的话,应用过的归档已经被删除,想回都回不去。

提 示: 如何知道当前逻辑Standby的参数设置呢?Oracle专门提供了一个数据字典DBA_LOGSTDBY_PARAMETERS,用于查询逻辑Standby当前的参数,例如:
SQL> SELECT * FROM DBA_LOGSTDBY_PARAMETERS;

NAME VALUE
—————————— ————————————————-
FIRST_SCN 580428
PREP_DICT_RECEIVED
PRIMARY 3409053734
LMNR_SID 1
GUARD_STANDBY READY
LOG_AUTO_DELETE FALSE
APPLY_SCN 581410

需要注意的是,如果禁止了Standby归档文件的自动删除功能,一定要有相应的其他解决方案,不能说取消了自动删除功能,之后逻辑Standby数据库接收到的Standby归档文件就不再管它,这肯定会产生问题,最起码要考虑到逻辑Standby数据库的存储空间是有限的。

逻辑Standby数据库接收到的归档文件并不会显示在V$ARCHIVED_LOG视图中,因此以为通过RMAN中的配置自动删除这些文件的希望也是会落空的。对于这类文件的删除,正确的删除方法通常会按照如下步骤操作:
首先执行DBMS_LOGSTDBY.PURGE_SESSION,该过程会检查当前所有接收到的归档日志文件,对于那些已经应用过,不再需要的文件进行标记,例如:
SQL> EXECUTE DBMS_LOGSTDBY.PURGE_SESSION;
PL/SQL procedure successfully completed.

然后,查询数据字典DBA_LOGMNR_PURGED_LOG,所有被DBMS_LOGSTDBY. PURGE_SESSION标记不再需要的日志都会记录在这里,例如:
SQL>SELECT * FROM DBA_LOGMNR_PURGED_LOG;
FILE_NAME
————————————————-
/U01/STD/ARC00109_0680477835.001
该字典只有一列,即归档文件的实际路径。最后根据显示的路径找到这些文件,然后在操作系统中删除即可。

3.2 启动实时应用
在默认情况下,逻辑Standby会等待单个归档文件全部接收之后再启动REDO应用,如果Standby数据库配置了Standby Redologs,就可以打开实时应用(Real-Time Apply),这样逻辑Standby端就不再需要等待接收完归档文件,只要有REDO数据写入本地的Standby Redologs,即可通过相应的进程实时写向逻辑Standby数据库。
启动逻辑Standby数据库的实时应用非常简单,只需要在逻辑Standby启动SQL应用时加上IMMEDIATE子句即可,例如:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

3.3 定义DBA_LOGSTDBY_EVENTS记录的事件
要查看逻辑Standby执行REDO应用时的操作信息,一般有两种方式:
一种是查看Oracle数据库的警告日志文件Alert(当然该文件不仅仅包括REDO应用的信息),
另一种是直接查询数据字典DBA_LOGSTDBY_EVENTS。

如果只是想查看日志应用信息的话,数据字典DBA_LOGSTDBY_EVENTS实用性更高,毕竟术业有专攻嘛。不过默认情况下该字典中只保留最近的100条消息(可以通过V$LOGSTDBY_STATS视图查看保留的记录数),这个数量过于偏小,如果要修改该字典中记录的事件数量,也是通过DBMS_LOGSTDBY.APPLY_SET过程完成。例如,设置该字典保留最近999条事件,执行语句如下:
JSSLDG> EXEC DBMS_LOGSTDBY.APPLY_SET(‘MAX_EVENTS_RECORDED’,’999′);
PL/SQL procedure successfully completed.

注 意: 执行DBMS_LOGSTDBY.APPLY_SET过程时,REDO应用必须处于停止状态。
SQL> alter database stop logical standby apply;
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

另外,还可以通过DBMS_LOGSTDBY.APPLY_SET过程设置是否记录DDL应用的事件,例如:
SQL> EXEC DBMS_LOGSTDBY.APPLY_SET(‘RECORD_APPLIED_DDL’,’TRUE’);
PL/SQL procedure successfully completed.

注:该过程同样要停REDO.

然后启动REDO应用,查看当前的最大保存记录数及是否记录DDL应用的事件:
SQL>ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.
SQL> select * from v$logstdby_stats where name in (‘maximum events recorded’,’record applied DDL’);

NAME VALUE
—————————— ————————————————-
maximum events recorded 999
record applied DDL N

四.修改逻辑Standby端数据
相对物理Standby,逻辑Standby的管理要复杂一点点。这个就是管理一个半数据库和管理两个数据库的差异(假设Data Guard环境为一主一备的情况下),毕竟逻辑Standby只是逻辑上,仿佛与Primary数据库一致,其实它是一个独立运行的,甚至可能与Primary数据库完全不同的数据库系统,对于这种配置环境,管理上多花点工夫想想也是应该的。

4.1 指定对象跳过应用
在默认情况下,接收自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外,其他都是可选参数,并且看字面意义就能明白其所指。例如,你想跳过SCOTT用户下对dept表的DML操作,可以通过执行下列语句实现(执行该过程前需要先停止REDO应用):
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.
SQL> EXEC DBMS_LOGSTDBY.SKIP(‘DML’, ‘SCOTT’, ‘DEPT’);
PL/SQL procedure successfully completed.
SQL>ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

4.2 恢复对象同步
如果逻辑Standby中的某些表取消了与Primary的同步维护,现在希望再恢复同步,没问题,DBMS_LOGSTDBY家大业大,它还有个叫UNSKIP的门生专干这个。
我们来看一下DBMS_LOGSTDBY.UNSKIP的语法:
DBMS_LOGSTDBY.UNSKIP (
stmt IN VARCHAR2,
schema_name IN VARCHAR2,
object_name IN VARCHAR2);
三项均为必选参数,各参数的定义与SKIP过程相同。

下面演示恢复tmp1表的同步。
首先查看当前逻辑Standby都有哪些对象处于不同步状态,可以通过DBA_LOGSTDBY_SKIP视图查看,例如:
SQL> select * from dba_logstdby_skip;
ERROR STATEMENT_OPT OWNER NAME U E PROC
—– —————————— ———- —– – – ———-
N DML SCOTT DEPT Y
N INTERNAL SCHEMA SYSTEM % Y
N INTERNAL SCHEMA SYS % Y
N INTERNAL SCHEMA OLAPSYS % Y
N INTERNAL SCHEMA SI_INFORMT % Y
N INTERNAL SCHEMA MGMT_VIEW % Y
N INTERNAL SCHEMA ORDPLUGINS % Y
N INTERNAL SCHEMA XDB % Y
N INTERNAL SCHEMA SYSMAN % Y
N INTERNAL SCHEMA WMSYS % Y
N INTERNAL SCHEMA DBSNMP % Y

注意在执行DBMS_LOGSTDBY.UNSKIP过程前,要停止当前的SQL应用状态:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.
执行DBMS_LOGSTDBY.UNSKIP过程,恢复前面停止的scott.tmp1表的应用:
SQL> execute dbms_logstdby.unskip(‘DML’, ‘SCOTT’, ‘dept’);
PL/SQL procedure successfully completed.

4.3 添加或重建对象
指定对象跳过应用虽然被取消,但是有可能在此期间由于Primary数据库做过数据修改,两端此时已经不同步,如果Standby端继续应用极有可能导致应用错误的数据。
对于这类情况,Oracle也早有预见,DBMS_LOGSTDBY包中还有一个过程叫INSTANTIATE_TABLE,专门用来同步一下跳过的对象,以保持与Primary数据库的一致。

DBMS_LOGSTDBY.INSTANTIATE_TABLE的调用语法如下:
DBMS_LOGSTDBY.INSTANTIATE_TABLE (
schema_name IN VARCHAR2,
table_name IN VARCHAR2,
dblink IN VARCHAR2);
除了SCHEMA名称和表名称外,还需要提供一个数据库链,因此这里我们首先在逻辑Standby端创建一个连接Primary数据库的数据库链:
SQL> CREATE DATABASE LINK PRE_TBL_DATA CONNECT TO SYSTEM IDENTIFIED BY ADMIN
USING ‘ORCL_PD’;
Database link created.
执行使用DBMS_LOGSTDBY.INSTANTIATE_TABLE过程,重新同步SCOTT.TMP1表(注意执行该过程前别忘了暂停当前的SQL应用):
SQL>EXEC DBMS_LOGSTDBY.INSTANTIATE_TABLE(‘SCOTT’, ‘DEPT’, ‘PRE_TBL_DATA’);
PL/SQL procedure successfully completed.
SQL> SELECT * FROM SCOTT.DEPT;

对象已被重建,然后重新启动SQL应用即可:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

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

在逻辑Standby端启动SQL应用的情况下,执行DDL操作:
SQL> GRANT DBA TO SCOTT;
Grant succeeded.
SQL> CONN SCOTT/TIGER;
Connected.
SQL> CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS;
CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS
*
ERROR at line 1:
ORA-01031: insufficient privileges

出错了,提示权限不足,实际上SCOTT被授予了DBA角色,肯定拥有CREATE TABLE权限的,因此此处与用户的权限无关,而是有其他因素制约了SCOTT无法进行修改。
下面禁用Data Guard保护之后,再次尝试操作数据:
SQL> ALTER SESSION DISABLE GUARD;
Session altered.
SQL> CREATE TABLE DAVE AS SELECT * FROM USER_OBJECTS;
Table created.
这下可以了,这就是Data Guard的作用。
注 意: 数据修改完之后,别忘了再次启用Data Guard,以避免不经意的误操作对逻辑Standby的配置造成影响(你说不手动启用Data Guard保护,直接退出行不行,当然也可以,ALTER SESSION所做修改仅对当前会话有效,退出重新登录,原会话设置自然就失效了)。
SQL> ALTER SESSION ENABLE GUARD;
Session altered.

按照Oracle的建议,还是尽可能不要在逻辑Standby端执行DML之类操作,以免破解其与Primary之间同步的逻辑关系,

也可以通过下列语句查看当前数据库是否处于Data Guard保护状态:
SQL> SELECT GUARD_STATUS FROM V$DATABASE;
GUARD_S
——-
ALL

该参数对应三个值:
ALL:表示对数据库中所有对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。
STANDBY:表示对处于逻辑Standby维护关系的对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。
NONE:不启动数据保护。

如果要永久设置数据库的Data Guard保护模式,则是通过ALTER DATABASE命令来完成,可指定的值也正是上述的三种,例如:
SQL> ALTER DATABASE GUARD STANDBY;
Database altered.

执行完上述语句后,Data Guard仅对处于逻辑Standby维护关系的对象进行防止修改操作的保护。

考虑到逻辑Standby中也有可能对数据进行修改(正如上例演示),因此这里引申谈一谈在逻辑Standby数据库中,约束和触发器的执行模式。默认情况下,约束和触发器都能在逻辑Standby端正常运行。约束和触发器在逻辑Standby端的执行可以分成两种情况:
对于SQL应用维护的约束和触发器,由于在Primary数据库已经检查过约束,因此Standby端不需要再次检查;触发器的情况也是这样,Primary端操作时结果已经被记录,因此逻辑Standby端将直接被应用,而不会二次触发。
对于没有SQL应用维护的约束和触发器,其执行情况与普通的Oracle数据库环境相同。

4.5 重定义REDO应用执行的操作
对于逻辑Standby数据库,你甚至可以通过编写自定义的PROCEDURE,来重新定义SQL应用时执行的操作。
如逻辑Standby数据库的文件路径与Primary数据库路径不同,如果是物理Standby,可以通过*_FILE_NAME_CONVERT之类的参数处理,在逻辑Standby环境中这几个参数无效,应该如何处理呢?答案就是通过编写自定义的过程,修改SQL应用时执行的操作。

下面通过示例,演示通过编写自定义的PROCEDURE,修改创建表空间时逻辑Standby端数据文件的路径。
首先当然是创建一个过程,建议创建在SYS下,因为在这个用户下的操作肯定不会有同步的问题,如下所示:
SQL> CREATE OR REPLACE PROCEDURE SYS.HANDLE_TBS_DDL (
2 OLD_STMT IN VARCHAR2,
3 STMT_TYP IN VARCHAR2,
4 SCHEMA IN VARCHAR2,
5 NAME IN VARCHAR2,
6 XIDUSN IN NUMBER,
7 XIDSLT IN NUMBER,
8 XIDSQN IN NUMBER,
9 ACTION OUT NUMBER,
10 NEW_STMT OUT VARCHAR2
11 ) AS
12 BEGIN
13
14 NEW_STMT := REPLACE(OLD_STMT, ‘/u01/oradata/orcl_pd/’, ‘/u01/oradata/orcl_st’);
15 ACTION := DBMS_LOGSTDBY.SKIP_ACTION_REPLACE;
16
17 EXCEPTION
18 WHEN OTHERS THEN
19 ACTION := DBMS_LOGSTDBY.SKIP_ACTION_ERROR;
20 NEW_STMT := NULL;
21 END HANDLE_TBS_DDL;
22 /
Procedure created.
逻辑非常简单,基本上就是一个REPLACE,不过PROCEDURE中声明的变量看起来很多,这个是固定格式,不建议修改。

停止逻辑Standby的SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.

如果不停,PROCEDURE不能生效。

执行DBMS_LOGSTDBY.SKIP过程,将编写的过程注册到表空间处理的SQL应用中:
SQL> EXEC DBMS_LOGSTDBY.SKIP (stmt => ‘TABLESPACE’,proc_name => ‘sys.handle_tbs_ddl’);
PL/SQL procedure successfully completed.

这里也要借助DBMS_LOGSTDBY.SKIP过程实现。该过程功能非常强大,而且操作非常灵活。

重启SQL应用:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

测试一下,在Primary端创建一个新的表空间:
SQL> CREATE TABLESPACE BOOKS DATAFILE ‘/u01/oradata/orcl_pd/books01.dbf’ SIZE 20m;
Tablespace created.
SQL> SELECT FILE_NAME FROM DBA_DATA_FILES WHERE TABLESPACE_NAME=’BOOKS’;
FILE_NAME
—————————————————————————–
/u01/oradata/orcl_pd/books01.dbf

转向逻辑Standby数据库查看:
SQL> SELECT FILE_NAME FROM DBA_DATA_FILES WHERE TABLESPACE_NAME=’BOOKS’;
FILE_NAME
—————————————————————————-
/u01/oradata/orcl_st/books01.dbf
表空间成功创建,并且数据文件路径也被转换为我们指定的路径。

此时如果你查看Alert日志文件,会发现其中记录下了类似这样的信息:
LOGSTDBY stmt: create tablespace books datafile ‘/u01/oradata/orcl_pd/books01.dbf’ size 20m
LOGSTDBY status: ORA-16110: 逻辑备用应用 DDL 的用户过程处理
LOGSTDBY id: XID 0x0001.009.000000d1, hSCN 0x0000.0012ec41,
lSCN 0x0000.0012ec41, Thread 1, RBA 0x007f.0000079a.80,
txnCscn 0x0000.0012ec43, PID 5816, ORACLE.EXE (P004)
LOGSTDBY stmt: create tablespace books datafile ‘/u01/oradata/orcl_st/books01.dbf’ size 20m
LOGSTDBY status: ORA-16202: 跳过过程已请求替换语句
LOGSTDBY id: XID 0x0001.009.000000d1, hSCN 0x0000.0012ec41,
lSCN 0x0000.0012ec41, Thread 1, RBA 0x007f.0000079a.80,
txnCscn 0x0000.0012ec43, PID 5816, ORACLE.EXE (P004)
create tablespace books datafile ‘/u01/oradata/orcl_st/books01.dbf’ size 20m
Completed: create tablespace books datafile ‘/u01/oradata/orcl_st/books01.dbf’ size 20m
LOGSTDBY stmt: create tablespace books datafile ‘/u01/oradata/orcl_st/books01.dbf’ size 20m
LOGSTDBY status: ORA-16204: 成功应用了 DDL

五.优化逻辑Standby数据同步性能

5.1 调整APPLIER进程数
APPLIER进程就是执行应用操作的进程。在默认情况下逻辑Standby会启动5个APPLIER进程,如果日志应用任务繁重(或者说Primary数据库修改量较大),则适当多启动几个APPLIER进程有助于提高应用的效率。

先查看当前空闲的APPLIER进程数:
SQL> SELECT COUNT(*) AS IDLE_APPLIER FROM V$LOGSTDBY_PROCESS WHERE TYPE = ‘APPLIER’ and status_code = 16166;

IDLE_APPLIER
————
0
返回结果为0,难道都在忙?这个真不一定,空闲的APPLIER进程数为0不一定代表应用非常繁忙,也有可能是因为当前没什么需要应用的日志,甚至都没启动应用进程。

说 明: status_code=16166表示进程是空闲状态,因为stats_code=16166对应的状态说明列STATS为ORA-16116: no work available。

检查事务的应用情况:
SQL> SELECT NAME,VALUE FROM V$LOGSTDBY_STATS WHERE NAME LIKE ‘transactions%’;
NAME VALUE
—– —————————
trans 358
trans 358

如果ready-applied的值比APPLIER进程数的两倍还要大,则说明DBA有必要考虑增加APPLIER进程的数目了,反之如果applied与ready的值差不多大,或者其差比APPLIER进程数还小,则说明APPLIER进程数偏多,DBA有必要考虑适当减小进程的数目。

如果确认当前APPLIER进程都非常繁忙,要增加APPLIER进程,可按如下步骤操作:

1) 停止逻辑Standby端的SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.

2) 执行下列语句,调整APPLIER进程数为10:
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET(‘APPLY_SERVERS’,10);
PL/SQL procedure successfully completed.

3) 重新启动SQL应用:
JSSLDG> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

4) 查出的就是当前运行的APPLIER进程数:
SQL> SELECT COUNT(0) FROM V$LOGSTDBY_PROCESS WHERE TYPE=’APPLIER’;
COUNT(0)
———-
10

也可以通过V$LOGSTDBY_STATS视图查询,例如:
SQL> SELECT * FROM V$LOGSTDBY_STATS WHERE NAME=’number of appliers’;

NAME VALUE
—– —————————————————————-
numbe 10

5.2 调整PREPARER进程数
PREPAPER进程将接收到的REDO数据中的块修改转换成LCRs(Logical Change Records)。一般需要调整PREPAPER进程数的机会不多,通常只有一种情况:APPLIER进程有空闲,Transactions Ready还很多,但没有空闲的PREPAPER进程,这时候DBA可能就需要增加一些PREPAPER进程。

先检查空闲PREPAPER进程数量:
SQL> SELECT COUNT(*) AS IDLE_PREPARER FROM V$LOGSTDBY_PROCESS
WHERE TYPE = ‘PREPARER’ and status_code = 16166;

IDLE_PREPARER
————-
0
说 明:如果显示为0,别怕,也有可能是因为当前没什么新的REDO数据需要处理。
如果确实需要调整PREPAPER进程数量,可以按照下列步骤进行。

首先停止SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.

调整PREPAPER进程数量为4(默认只有1个PREPAPER进程):
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET(‘PREPARE_SERVERS’,4);
PL/SQL procedure successfully completed.

重新启动SQL应用即可:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

查看当前启动的PREPAPER进程数, 查询V$LOGSTDBY_STATS视图,例如:
SQL> SELECT * FROM V$LOGSTDBY_STATS WHERE NAME=’number of preparers’;
NAME VALUE
—– —————————————————————-
numbe 4

5.3 调整LCR使用的内存
LCR中保存的是转换后的块修改的记录,这部分数据保存在SGA中.

查询当前LCR可用的最大内存:
SQL> SELECT * FROM V$LOGSTDBY_STATS WHERE NAME=’maximum SGA for LCR cache’;
NAME VALUE
———————————— ——————–
maximum SGA for LCR cache 30

显示的参数值默认单位为M,当前结果显示LCR内存区可用空间为30M。

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

1) 首先还是需要停止SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
Database altered.

2) 调整内存大小为100M:
SQL> EXEC DBMS_LOGSTDBY.APPLY_SET(‘MAX_SGA’,100);
PL/SQL procedure successfully completed.

3)最后重启SQL应用即可
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;
Database altered.

5.4 调整事务应用方式
在默认情况下逻辑Standby端事务应用顺序与Primary数据库提交顺序相同。如果DBA希望逻辑Standby端事务应用不按照Primary数据库顺序执行的话,可以按照下列步骤操作:

1)停止SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;

2)允许事务不按照Primary的提交顺序应用:
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_SET(‘PRESERVE_COMMIT_ORDER’, ‘FALSE’);

3)重新启动SQL应用:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

恢复逻辑Standby按照事务提交顺序应用的话,可按照下列步骤操作:

1)先停止SQL应用:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;

2)重置参数PRESERVE_COMMIT_ORDER的初始值:
SQL> EXECUTE DBMS_LOGSTDBY.APPLY_UNSET(‘PRESERVE_COMMIT_ORDER’);

3)重新启动SQL应用:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

六.应用REDO数据到Standby数据库
1.物理Standby应用REDO数据
物理Standby启动REDO应用,数据库要处于MOUNT状态或是OPEN READ ONLY状态,启动REDO应用的命令相信大家已经非常熟悉了。

前台应用:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE;
语句执行完成后,不会将控制权返回到命令行窗口,除非你手动中止应用。在这种情况下如果还需要对数据库进行操作,只能新开一个命令行连接,在Oracle 8i刚推出Standby特性时(那时不叫Data Guard),只提供了这种方式。

后台应用:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT;
这是现在比较通用的方式,语句执行完后,控制权自动返回到当前的命令行模式,REDO应用以后台进程运行。

启动实时应用,附加USING CURRENT LOGFILE子句即可:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE;

如果要停止REDO应用,执行下列语句即可:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE CANCEL;

2.逻辑Standby应用REDO数据
SQL应用的原理是将接收到的REDO数据转换成SQL语句在逻辑Standby数据库端执行,因此逻辑Standby需要启动至OPEN状态。
(1)启动SQL应用。逻辑Standby数据库启动SQL应用没有前、后台运行之说,语句执行完之后,控制权就会自动返回当前命令行窗口。要启动SQL应用,直接执行下列语句即可:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY;

如果要启动实时应用,附加IMMEDIATE子句即可,例如:
SQL> ALTER DATABASE START LOGICAL STANDBY APPLY IMMEDIATE;

(2)停止SQL应用,如:
SQL> ALTER DATABASE STOP LOGICAL STANDBY APPLY;
由于是执行SQL语句的方式应用REDO数据,因此上述语句的执行需要等待当前执行的SQL触发的事务结束,才能真正停止REDO应用的状态。

如果不考虑事务执行情况,马上停止REDO应用,可以通过下列的语句来完成:
SQL> ALTER DATABASE ABORT LOGICAL STANDBY APPLY;

continuing ……

reference:http://blog.csdn.net/tianlesoftware/article/details/5564208