Oracle Data Gurad -- Logical Standby 相关说明

一.逻辑Standby的准备工作

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

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

(1)并非所有的数据类型都能被逻辑Standby支持

逻辑Standby支持的数据类型有:

BINARY_DOUBLEBINARY_FLOATBLOBCHARCLOBandNCLOBDATEINTERVALYEARTOMONTHINTERVALDAYTOSECONDLONGLONGRAWNCHARNUMBERNVARCHAR2RAWTIMESTAMP

TIMESTAMPWITHLOCALTIMEZONETIMESTAMPWITHTIMEZONEVARCHAR2andVARCHAR

说明:下列类型在获取Standby支持时需要注意兼容性:

CLOB,需要Primary数据库的兼容级别运行于10.1或更高。

LOB字段的索引组织表(IOT),需要Primary数据库的兼容级别运行于10.2或更高。

不含LOB字段的索引组织表(IOT),需要Primary数据库的兼容级别运行于10.1或更高。

不支持的数据类型有:

BFILEEncryptedColumnsROWID,UROWIDXMLType、对象类型、VARRAYS、嵌套表、自定义类型。

可以通过查询DBA_LOGSTDBY_UNSUPPORTED来确定主数据库中是否含有不支持的对象

SQL>select*fromdba_logstdby_unsupported;

注意该视图的ATTRIBUTES列,显示对象不被SQL应用支持的原因。

2)并非所有的存储类型都能被逻辑Standby支持。

逻辑Standby能够支持簇表(ClusterTables)、索引组织表(Index-OrganizedTables)、堆组织表(Heap-OrganizedTables),但不支持段压缩(SegmentCompression)存储类型。

3)并非所有的PL/SQL包都能被SQL应用支持。

通常那些不会修改系统元数据(Metadata)的Package在实际应用时不会有问题,如DBMS_OUTPUTDBMS_RANDOMDBMS_METADATA之类的包。

那些可能修改系统元数据的Package不会被SQL应用支持,即使它们在Primary执行过,并且被成功传输到逻辑Standby端,也不会执行。如DBMS_JAVADBMS_REGISTRYDBMS_ALERTDBMS_SPACE_ADMINDBMS_REFRESHDBMS_REDEFINITIONDBMS_SCHEDULERDBMS_AQ等。只有DBMS_JOB例外,Primary数据库的jobs会被复制到逻辑Standby,不过在逻辑Standby数据库不会执行这些job

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

4)并非所有的SQL语句都能在逻辑Standby端执行。

在默认情况下,下列SQL语句在逻辑Standby端会被SQL应用自动跳过:

ALTERDATABASE

ALTERMATERIALIZEDVIEW

ALTERMATERIALIZEDVIEWLOG

ALTERSESSION

ALTERSYSTEM

CREATECONTROLFILE

CREATEDATABASE

CREATEDATABASELINK

CREATEPFILEFROMSPFILE

CREATEMATERIALIZEDVIEW

CREATEMATERIALIZEDVIEWLOG

CREATESCHEMAAUTHORIZATION

CREATESPFILEFROMPFILE

DROPDATABASELINK

DROPMATERIALIZEDVIEW

DROPMATERIALIZEDVIEWLOG

EXPLAIN

LOCKTABLE

SETCONSTRAINTS

SETROLE

SETTRANSACTION

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

5)并非所有的DML操作都能在逻辑Standby端实面SQL应用。

维护逻辑StandbyPrimary的数据库同步是通过SQL应用实现,SQL应用转换的SQL语句在执行时,对于INSERT还好说,对于UPDATEDELETE操作则必须能够唯一定位到数据库待更新的那条记录。问题就在这里,如果Primary库中表设置不当,可能就无法确认唯一条件。

你可能会说可以通过ROWID唯一嘛!千万要谨记啊,逻辑Standby,为啥叫逻辑Standby,就是因为它只是逻辑上与Primary数据库相同,物理上可能与Primary数据库存在相当大差异。一定要认识到,逻辑Standby的物理结构与Primary是不相同的(即使初始逻辑Standby是通过Primary的备份创建)。

因此想通过ROWID更新显然是不好使的,当然也就不能再将其作为唯一条件。下面来看这个问题。

2确保Primary库中各表的行可被唯一标识

Oracle通过主键、唯一索引/约束的补充日志(SupplementalLogging来确定待更新逻辑Standby数据库中的行。当数据库启用了补充日志,每一条UPDATE语句写REDO的时候会附加列值唯一信息,比如:

如果表定义了主键,则主键列会随同被更新列一起作为UPDATE语句的一部分,以便执行时区分哪些列应该被更新。

如果没有主键,则非空的唯一索引/约束会随同被更新列作为UPDATE语句的一部分,以便执行时区分哪些列应该被更新,如果该表有多个唯一索引/约束,则Oracle自动选择长度最短的那个,以降低生成的重做日志大小。

如果表既无主键,也没有定义唯一索引/约束,所有可定长度的列,连同被更新列同时作为UPDATE语句的一部分。更明确些,可定长度的列是指除LONGLOBLONGRAWOBJECTTYPECOLLECTION类型外的列。

Oracle建议你为表创建一个主键或非空的唯一索引/约束,以尽可能确保SQL应用能够有效应用REDO数据,更新逻辑Standby数据库。

下列语句可以用来检查SQL应用能否唯一识别表列,并找出不被支持的表:

SQL>SELECTOWNER,TABLE_NAMEFROMDBA_LOGSTDBY_NOT_UNIQUEWHERE(OWNER,TABLE_N

AME)NOTIN(SELECTDISTINCTOWNER,TABLE_NAMEFROMDBA_LOGSTDBY_UNSUPPORTED)

ANDBAD_COLUMN='Y';

OWNERTABLE_NAME

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

TSMSYSRS$

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

注意BAD_COLUMN值,该列有两个值:

Y:表示该表中有采用大数据类型的字段,比如LONGCLOB。如果表中除LOG列某些行记录完全匹配,则该表无法成功应用于逻辑StandbyStandby会尝试维护这些表,不过你必须保证应用不允许。

N:表示该表拥有足够的信息,能够支持在逻辑Standby的更新,不过仍然建议你为该表创建一个主键或者唯一索引/约束,以提高LOG应用效率。

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

提示:关于Primary-KeyRely约束。

如果DBA能够确认表中的行是唯一的,那么可以为该表创建Rely的主键,Rely约束并不会造成系统维护主键的开销,如你对一个表创建了RELY约束,系统则会假定该表中的行是唯一的,这样能够提高SQL应用时的性能。但是需要注意,由于Rely的主键约束只是假定唯一,如果实际并不唯一的话,有可能会造成错误的更新哟。

创建Rely的主键约束非常简单,只要在标准的创建语句后加上RELYDISABLE即可,例如:

SQL>ALTERTABLEUSERADDPRIMARYKEY(ID)RELYDISABLE;

表已更改。

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

二.逻辑Standby创建时的操作步骤

1创建物理Standby

创建逻辑Standby数据库的第一步就是先创建一个物理Standby数据库,然后再将其转换成逻辑Standby数据库。在将其转换为逻辑Standby前,可以随时启动REDO应用,不过一旦决定将其转换为逻辑Standby,就必须先停止该物理StandbyREDO应用,以避免提前应用含LogMiner字典的REDO数据,造成转换为逻辑Standby后,SQL应用时LogMiner字典数据不足而影响到逻辑StandbyPrimary的正常同步。

2设置Primary数据库

在创建物理Standby数据库时曾经设置过相关数量的初始化参数,用于Primary数据库与物理Standby的角色切换,对于逻辑Standby的角色切换,那些参数同样好使。

不过注意,如果希望Primary数据库能够正常切换为逻辑Standby角色,那么DBA在配置环境时,还需要设置相应的LOG_ARCHIVE_DEST_n初始化参数,并注意该参数的VALID_FOR属性值需要更改成STANDBY_LOGFILES,STANDBY_ROLE

完成对初始化参数的配置后,必须在Primary数据库端生成LogMiner字典信息,例如:

SQL>EXECUTEDBMS_LOGSTDBY.BUILD;

提示本步必须执行,并且执行本步操作时,准逻辑Standby数据库要停止REDO应用。

该过程专门用于生成记录的元数据信息到重做日志文件,逻辑Standby未来正是通过这些元数据保持与Primary数据库的同步。

提示该过程会自动启用Primary数据库的补充日志(SupplementalLogging)功能(如果未启用的话)。

该过程需要等待当前所有事务完成后才能执行,因此如果当前有较长的事务运行,可能该过程的执行也需要多花一些等待时间。

该过程是通过闪回查询的方式来获取数据字典的一致性,因此Oracle初始化参数UNDO_RETENTION值不能太小,建议设置为3600,并且UNDO表空间也要有足够的空间。

3转换物理Standby为逻辑Standby

执行下列语句,转换物理Standby为逻辑Standby

SQL>ALTERDATABASERECOVERTOLOGICALSTANDBYDB_NAME;

注意:DB_NAME不是DB_UNIQUE_NAME,不同于物理Standby逻辑Standby是一个全新的数据库,因此建议你指定一个唯一的与Primary不同的数据库名。另外如果当前准逻辑Standby使用SPFILE启动数据库,那么执行该语句时Oracle会自动修改SPFILE中的相关信息,如果使用PFILE启动数据库,那么在下次执行SHUTDOWN的时候,Oracle会提示你去修改DB_NAME初始化参数的值。

执行该语句前务必确保当前准逻辑Standby已经暂停了REDO应用,另外转换是单向的,即只能由物理Standby向逻辑Standby转换,而不能由逻辑Standby转成物理Standby。这并不仅仅是因为DB_NAME发生了修改,更主要的原因是逻辑Standby仅是数据与Primary一致,其他如存储结构、SCN等,甚至DBID都不相同。

执行转换的过程中,需要应用全部的与LogMiner字典相关的REDO数据。这部分操作完全依赖于Primary数据库DBMS_LOGSTDBY.BUILD的执行,以及传输到Standby数据库端,需要应用的数据量的规模而定。如果Primary数据库执行DBMS_LOGSTDBY.BUILD失败,则转换操作也不会有结果,这时候你恐怕不得不先cancel它,解决Primary数据库的问题之后再尝试执行转换。取消该操作与取消REDO应用一样,当然实际上,也正是取消REDO应用。

4重建逻辑Standby的密钥文件

主要是由于转换操作修改了数据库名,因此密码文件也需要重建,这个操作我们做得比较多,这里就不详述了。

[oracle@localhostdbs]$orapwdfile=/u01/app/oracle/product/10.2.0/db_1/dbs/orapworclpassword=admin

如果已经存在,就不用创建了。缺省情况下,win下口令文件的格式是pwdsid.oraunix下的格式是orapwSID(大小写敏感)

5调整逻辑Standby初始化参数

之所以要调整初始化参数,一方面是由于此处我们的逻辑Standby是从物理Standby转换来的,某些参数并不适合,甚至可能造成错误,如LOG_ARCHIVE_DEST_n参数的设置。另一方面,由于逻辑Standby默认是以OPENREADWRITE模式打开,有可能存在读写操作,因此会读写本地OnlineRedologs并产生ArchiveLogs,务必需要注意本地的ArchiveLogs路径,不要与接收自Primary数据库的重做日志文件路径冲突。

当然归根结底是因为逻辑Standby是从物理Standby转换而来,因此Standby的初始化参数就需要第二次调整(第一次是创建物理Standby)。

修改初始化参数的方式有多种,既可以通过ALTERSYSTEM命令,也可以先生成PFILE并修改相关参数,然后再根据修改过的PFILE生成SPFILE

6打开逻辑Standby及应用REDO数据

由于逻辑StandbyPrimary数据库事务并不一致,其实质相当于进行了不完全恢复,因此第一次打开时必须指定RESETLOGS子句,如下:

SQL>ALTERDATABASEOPENRESETLOGS;

在逻辑Standby端启动SQL应用,可以通过下列语句进行:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLY;

注意应用REDO数据时必须是在OPENREADWRITE模式下,这点与物理Standby有明显的区别。

逻辑Standby也可以像物理Standby那样启用实时应用,只需要在启动REDO应用时附加IMMEDIATE子句即可,如:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

如果想停止逻辑Standby数据库的SQL应用,则可通过下列命令进行:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLYIMMEDIATE;

关于LogicalStandby完成创建实例及主备切换,请参考blog

OracleDataGuardLinux平台LogicalStandby创建实例

http://blog.csdn.net/tianlesoftware/archive/2010/05/06/5564179.aspx

三.管理逻辑Standby的相关视图

1DBA_LOGSTDBY_EVENTS

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

例如:

SQL>SELECTEVENT_TIME,STATUS,EVENTFROMDBA_LOGSTDBY_EVENTS

ORDERBYEVENT_TIMESTAMP;

EVENT_TIMSTATUSEVENT

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

05-MAY-10ORA-16111:logminingandapplysettingup

05-MAY-10ORA-16257:Switchoverinitiatedstopapplysuccess

2DBA_LOGSTDBY_LOG

该视图用来记录当前的重做日志的应用情况,功能类似于物理Standby中的V$ARCHIVED_LOG

多数情况下,你只需要关注SEQUENCE#APPLIED等有限的几个列,即查看日志序号和是否应用,当然该视图还能提供更多信息,如应用的SCN、应用时间等,例如:

SQL>SELECTSEQUENCE#,FIRST_CHANGE#,NEXT_CHANGE#,

TIMESTAMP,APPLIEDFROMDBA_LOGSTDBY_LOG;

SEQUENCE#FIRST_CHANGE#NEXT_CHANGE#TIMESTAMPAPPLIED

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

11057216057217105-MAY-10CURRENT

11157217157217505-MAY-10NO

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

3V$LOGSTDBY_STATS

该视图就是用来显示LogMiner的状态等相关信息,例如:

SQL>SELECT*FROMV$LOGSTDBY_STATS;

NAMEVALUE

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

numberofpreparers1

numberofappliers5

maximumSGAforLCRcache30

parallelserversinuse9

maximumeventsrecorded100

preservecommitorderTRUE

transactionconsistencyFULL

recordskiperrorsY

recordskipDDLY

recordappliedDDLN

recordunsupportedoperationsN

4V$LOGSTDBY_PROCESS

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

身份信息:SIDSERIAL#SPID

SQL应用进程:COORDINATORREADERBUILDERPREPARERANALYZER、或APPLIER

进程当前的状态:见STATUS_CODESTATUS列。

该进程当前操作REDO记录最大SCNHIGH_SCN列。

例如:

SQL>SELECTSID,SERIAL#,SPID,TYPE,STATUS,HIGH_SCNFROMV$LOGSTDBY_PROCESS;

SIDSERIAL#SPIDTYPESTATUS

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

1393036831COORDINATORORA-16116:noworkavailable

1532926833READERORA-16240:Waitingforlogfil

13656835BUILDERORA-16116:noworkavailable

13756837PREPARERORA-16116:noworkavailable

12816841ANALYZERORA-16116:noworkavailable

13216843APPLIERORA-16116:noworkavailable

13326845APPLIERORA-16116:noworkavailable

13016847APPLIERORA-16116:noworkavailable

12916849APPLIERORA-16116:noworkavailable

13116851APPLIERORA-16116:noworkavailable

5V$LOGSTDBY_PROGRESS

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

例如,查看当前应用的SCN信息:

SQL>SELECTAPPLIED_SCN,LATEST_SCN,MINING_SCN,RESTART_SCNFROMV$LOGSTDBY_PROGRESS;

APPLIED_SCNLATEST_SCNMINING_SCNRESTART_SCN

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

572164572232572166

6V$LOGSTDBY_STATE

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

1)INITIALIZING初始化状态。

执行ALTERDATABASESTARTLOGICALSTANDBYAPPLY语句,启动SQL应用时,首先就会进入初始化状态,例如:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

SQL>SELECTSESSION_ID,STATEFROMV$LOGSTDBY_STATE;

SESSION_IDSTATE

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

21INITIALIZING

这个状态存在的时间非常短暂,多数情况下只有当ALTERDATABASESTARTLOGICALSTANDBYAPPLY执行时查看V$LOGSTDBY_STATE视图,会看到初始化状态,一旦该命令执行完,状态就被切换为等待字典日志或应用中的状态了。

2)WAITINGFORDICTIONARYLOGS等待数据字典日志。

指第一次初始化时的状态,如刚从物理Standby转换成逻辑Standby,需要首先应用来自Primary端生成的数据字典,在等待Primary数据字典信息时,就会处于这一状态。例如:

SQL>SELECTSESSION_ID,STATEFROMV$LOGSTDBY_STATE;

SESSION_IDSTATE

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

21WAITINGFORDICTIONARYLOGS

这个过程也非常短暂。

3)LOADINGDICTIONARY加载并分析。

当查询V$LOGSTDBY_STATE视图,显示下列状态时,说明处于加载数据字典的状态:

SQL>SELECTSESSION_ID,STATEFROMV$LOGSTDBY_STATE;

SESSION_IDSTATE

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

21LOADINGDICTIONARY

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

SQL>SELECTPERCENT_DONE,COMMANDFROMV$LOGMNR_DICTIONARY_LOAD

WHERESESSION_ID=(SELECTSESSION_IDFROMV$LOGSTDBY_STATE);

APPLYING应用REDO数据。

SQL应用正在处理中,如果要查看当前的处理进度,可以通过V$LOGSTDBY_PROGRESS视图完成。

4)WAITINGONGAP中断等待状态。

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

5)IDLE空闲状态。

处于这一状态也有可能不是好现象,一方面可能是逻辑Standby处理能力优秀,所有活都干完了;也可能是Primary数据库发送日志或逻辑Standby日志出现了问题,导致SQL应用无活可干,因此处于空闲状态。

如果你发现你的逻辑Standby数据库长期处于这一状态,建议查询DBA_LOGSTDBY_LOG视图,确认Primary端产生的日志文件能被逻辑Standby数据库正常接收。

6)SQLAPPLYNOTON

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

四.逻辑Standby数据库的自定义配置

4.1取消自动删除归档文件

逻辑Standby应用完归档后会自动删除该归档文件,这一极具体贴意味的特性,是由逻辑Standby中的一项参数控制的,如果希望禁用自动删除的功能,可以执行下列语句:

SQL>EXECDBMS_LOGSTDBY.APPLY_SET('LOG_AUTO_DELETE','FALSE');

PL/SQLproceduresuccessfullycompleted.

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

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

SQL>SELECT*FROMDBA_LOGSTDBY_PARAMETERS;

NAMEVALUE

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

FIRST_SCN580428

PREP_DICT_RECEIVED

PRIMARY3409053734

LMNR_SID1

GUARD_STANDBYREADY

LOG_AUTO_DELETEFALSE

APPLY_SCN581410

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

逻辑Standby数据库接收到的归档文件并不会显示在V$ARCHIVED_LOG视图中,因此以为通过RMAN中的配置自动删除这些文件的希望也是会落空的。对于这类文件的删除,正确的删除方法通常会按照如下步骤操作:

首先执行DBMS_LOGSTDBY.PURGE_SESSION,该过程会检查当前所有接收到的归档日志文件,对于那些已经应用过,不再需要的文件进行标记,例如:

SQL>EXECUTEDBMS_LOGSTDBY.PURGE_SESSION;

PL/SQLproceduresuccessfullycompleted.

然后,查询数据字典DBA_LOGMNR_PURGED_LOG,所有被DBMS_LOGSTDBY.PURGE_SESSION标记不再需要的日志都会记录在这里,例如:

SQL>SELECT*FROMDBA_LOGMNR_PURGED_LOG;

FILE_NAME

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

/U01/STD/ARC00109_0680477835.001

该字典只有一列,即归档文件的实际路径。最后根据显示的路径找到这些文件,然后在操作系统中删除即可。

4.2启动实时应用

在默认情况下,逻辑Standby会等待单个归档文件全部接收之后再启动REDO应用,如果Standby数据库配置了StandbyRedologs,就可以打开实时应用(Real-TimeApply),这样逻辑Standby端就不再需要等待接收完归档文件,只要有REDO数据写入本地的StandbyRedologs,即可通过相应的进程实时写向逻辑Standby数据库。

启动逻辑Standby数据库的实时应用非常简单,只需要在逻辑Standby启动SQL应用时加上IMMEDIATE子句即可,例如:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

4.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>EXECDBMS_LOGSTDBY.APPLY_SET('MAX_EVENTS_RECORDED','999');

PL/SQLproceduresuccessfullycompleted.

注意:执行DBMS_LOGSTDBY.APPLY_SET过程时,REDO应用必须处于停止状态。

SQL>alterdatabasestoplogicalstandbyapply;

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

另外,还可以通过DBMS_LOGSTDBY.APPLY_SET过程设置是否记录DDL应用的事件,例如:

SQL>EXECDBMS_LOGSTDBY.APPLY_SET('RECORD_APPLIED_DDL','TRUE');

PL/SQLproceduresuccessfullycompleted.

注:该过程同样要停REDO.

然后启动REDO应用,查看当前的最大保存记录数及是否记录DDL应用的事件:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

SQL>select*fromv$logstdby_statswherenamein('maximumeventsrecorded','recordappliedDDL');

NAMEVALUE

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

maximumeventsrecorded999

recordappliedDDLN

五.修改逻辑Standby端数据

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

5.1指定对象跳过应用

在默认情况下,接收自PrimaryREDO数据中,所有能够被逻辑Standby数据库支持的操作都会在逻辑Standby端执行。如果你希望跳过对某些对象的某些操作的话,DBMS_LOGSTDBY.SKIP就能派上用场了。

先来看看DBMS_LOGSTDBY.SKIP的语法:

DBMS_LOGSTDBY.SKIP(

stmtINVARCHAR2,

schema_nameINVARCHAR2DEFAULTNULL,

object_nameINVARCHAR2DEFAULTNULL,

proc_nameINVARCHAR2DEFAULTNULL,

use_likeINBOOLEANDEFAULTTRUE,

escINCHAR1DEFAULTNULL);

stmt外,其他都是可选参数,并且看字面意义就能明白其所指。例如,你想跳过SCOTT用户下对dept表的DML操作,可以通过执行下列语句实现(执行该过程前需要先停止REDO应用):

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

SQL>EXECDBMS_LOGSTDBY.SKIP('DML','SCOTT','DEPT');

PL/SQLproceduresuccessfullycompleted.

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

5.2恢复对象同步

如果逻辑Standby中的某些表取消了与Primary的同步维护,现在希望再恢复同步,没问题,DBMS_LOGSTDBY家大业大,它还有个叫UNSKIP的门生专干这个。

我们来看一下DBMS_LOGSTDBY.UNSKIP的语法:

DBMS_LOGSTDBY.UNSKIP(

stmtINVARCHAR2,

schema_nameINVARCHAR2,

object_nameINVARCHAR2);

三项均为必选参数,各参数的定义与SKIP过程相同。

下面演示恢复tmp1表的同步。

首先查看当前逻辑Standby都有哪些对象处于不同步状态,可以通过DBA_LOGSTDBY_SKIP视图查看,例如:

SQL>select*fromdba_logstdby_skip;

ERRORSTATEMENT_OPTOWNERNAMEUEPROC

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

NDMLSCOTTDEPTY

NINTERNALSCHEMASYSTEM%Y

NINTERNALSCHEMASYS%Y

NINTERNALSCHEMAOLAPSYS%Y

NINTERNALSCHEMASI_INFORMT%Y

NINTERNALSCHEMAMGMT_VIEW%Y

NINTERNALSCHEMAORDPLUGINS%Y

NINTERNALSCHEMAXDB%Y

NINTERNALSCHEMASYSMAN%Y

NINTERNALSCHEMAWMSYS%Y

NINTERNALSCHEMADBSNMP%Y

注意在执行DBMS_LOGSTDBY.UNSKIP过程前,要停止当前的SQL应用状态:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

执行DBMS_LOGSTDBY.UNSKIP过程,恢复前面停止的scott.tmp1表的应用:

SQL>executedbms_logstdby.unskip('DML','SCOTT','dept');

PL/SQLproceduresuccessfullycompleted.

5.3添加或重建对象

指定对象跳过应用虽然被取消,但是有可能在此期间由于Primary数据库做过数据修改,两端此时已经不同步,如果Standby端继续应用极有可能导致应用错误的数据。

对于这类情况,Oracle也早有预见,DBMS_LOGSTDBY包中还有一个过程叫INSTANTIATE_TABLE,专门用来同步一下跳过的对象,以保持与Primary数据库的一致。

DBMS_LOGSTDBY.INSTANTIATE_TABLE的调用语法如下:

DBMS_LOGSTDBY.INSTANTIATE_TABLE(

schema_nameINVARCHAR2,

table_nameINVARCHAR2,

dblinkINVARCHAR2);

除了SCHEMA名称和表名称外,还需要提供一个数据库链,因此这里我们首先在逻辑Standby端创建一个连接Primary数据库的数据库链:

SQL>CREATEDATABASELINKPRE_TBL_DATACONNECTTOSYSTEMIDENTIFIEDBYADMIN

USING'ORCL_PD';

Databaselinkcreated.

执行使用DBMS_LOGSTDBY.INSTANTIATE_TABLE过程,重新同步SCOTT.TMP1表(注意执行该过程前别忘了暂停当前的SQL应用):

SQL>EXECDBMS_LOGSTDBY.INSTANTIATE_TABLE('SCOTT','DEPT','PRE_TBL_DATA');

PL/SQLproceduresuccessfullycompleted.

SQL>SELECT*FROMSCOTT.DEPT;

对象已被重建,然后重新启动SQL应用即可:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

5.4逻辑Standby端修改数据

逻辑Standby的一个极具实用价值的特性就是可以边查询边应用,因此将其作为报表服务器专供查询是个很不错的想法,而且逻辑Standby相对于物理Standby而言更具灵活性,如我们可以在逻辑Standby上,对一些表创建Primary数据库并不方便创建的索引、约束,甚至可以做DML/DDL操作(当然,需要注意不要破坏了与Primary数据库之间同步的逻辑关系)。

不过由于此时DataGuard仍然控制着对逻辑Standby数据库中表的读写操作,因此,如果你想对逻辑Standby中的数据做些什么的话,ALTERSESSIONDISABLE|ENABLEGUARD语句就必须牢记在心了,它拥有像"芝麻开门"一样神奇的能力下面我们就来感受一下吧。

在逻辑Standby端启动SQL应用的情况下,执行DDL操作:

SQL>GRANTDBATOSCOTT;

Grantsucceeded.

SQL>CONNSCOTT/TIGER;

Connected.

SQL>CREATETABLEDAVEASSELECT*FROMUSER_OBJECTS;

CREATETABLEDAVEASSELECT*FROMUSER_OBJECTS

*

ERRORatline1:

ORA-01031:insufficientprivileges

出错了,提示权限不足,实际上SCOTT被授予了DBA角色,肯定拥有CREATETABLE权限的,因此此处与用户的权限无关,而是有其他因素制约了SCOTT无法进行修改。

下面禁用DataGuard保护之后,再次尝试操作数据:

SQL>ALTERSESSIONDISABLEGUARD;

Sessionaltered.

SQL>CREATETABLEDAVEASSELECT*FROMUSER_OBJECTS;

Tablecreated.

这下可以了,这就是DataGuard的作用。

注意数据修改完之后,别忘了再次启用DataGuard,以避免不经意的误操作对逻辑Standby的配置造成影响(你说不手动启用DataGuard保护,直接退出行不行,当然也可以,ALTERSESSION所做修改仅对当前会话有效,退出重新登录,原会话设置自然就失效了)。

SQL>ALTERSESSIONENABLEGUARD;

Sessionaltered.

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

可以通过下列语句查看当前数据库是否处于DataGuard保护状态:

SQL>SELECTGUARD_STATUSFROMV$DATABASE;

GUARD_S

-------

ALL

该参数对应三个值:

ALL表示对数据库中所有对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。

STANDBY表示对处于逻辑Standby维护关系的对象启动修改保护,除SYS用户外,其他用户均不能直接修改数据。

NONE不启动数据保护。

如果要永久设置数据库的DataGuard保护模式,则是通过ALTERDATABASE命令来完成,可指定的值也正是上述的三种,例如:

SQL>ALTERDATABASEGUARDSTANDBY;

Databasealtered.

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

考虑到逻辑Standby中也有可能对数据进行修改(正如上例演示),因此这里引申谈一谈在逻辑Standby数据库中,约束和触发器的执行模式。默认情况下,约束和触发器都能在逻辑Standby端正常运行。约束和触发器在逻辑Standby端的执行可以分成两种情况:

对于SQL应用维护的约束和触发器,由于在Primary数据库已经检查过约束,因此Standby端不需要再次检查;触发器的情况也是这样,Primary端操作时结果已经被记录,因此逻辑Standby端将直接被应用,而不会二次触发。

对于没有SQL应用维护的约束和触发器,其执行情况与普通的Oracle数据库环境相同。

5.5重定义REDO应用执行的操作

对于逻辑Standby数据库,你甚至可以通过编写自定义的PROCEDURE,来重新定义SQL应用时执行的操作。

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

下面通过示例,演示通过编写自定义的PROCEDURE,修改创建表空间时逻辑Standby端数据文件的路径。

首先当然是创建一个过程,建议创建在SYS下,因为在这个用户下的操作肯定不会有同步的问题,如下所示:

SQL>CREATEORREPLACEPROCEDURESYS.HANDLE_TBS_DDL(

2OLD_STMTINVARCHAR2,

3STMT_TYPINVARCHAR2,

4SCHEMAINVARCHAR2,

5NAMEINVARCHAR2,

6XIDUSNINNUMBER,

7XIDSLTINNUMBER,

8XIDSQNINNUMBER,

9ACTIONOUTNUMBER,

10NEW_STMTOUTVARCHAR2

11)AS

12BEGIN

13

14NEW_STMT:=REPLACE(OLD_STMT,'/u01/oradata/orcl_pd/','/u01/oradata/orcl_st');

15ACTION:=DBMS_LOGSTDBY.SKIP_ACTION_REPLACE;

16

17EXCEPTION

18WHENOTHERSTHEN

19ACTION:=DBMS_LOGSTDBY.SKIP_ACTION_ERROR;

20NEW_STMT:=NULL;

21ENDHANDLE_TBS_DDL;

22/

Procedurecreated.

逻辑非常简单,基本上就是一个REPLACE,不过PROCEDURE中声明的变量看起来很多,这个是固定格式,不建议修改。

停止逻辑StandbySQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

如果不停PROCEDURE生效。

执行DBMS_LOGSTDBY.SKIP过程,将编写的过程注册到表空间处理的SQL应用中:

SQL>EXECDBMS_LOGSTDBY.SKIP(stmt=>'TABLESPACE',proc_name=>'sys.handle_tbs_ddl');

PL/SQLproceduresuccessfullycompleted.

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

重启SQL应用:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

测试一下,在Primary端创建一个新的表空间:

SQL>CREATETABLESPACEBOOKSDATAFILE'/u01/oradata/orcl_pd/books01.dbf'SIZE20m;

Tablespacecreated.

SQL>SELECTFILE_NAMEFROMDBA_DATA_FILESWHERETABLESPACE_NAME='BOOKS';

FILE_NAME

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

/u01/oradata/orcl_pd/books01.dbf

转向逻辑Standby数据库查看:

SQL>SELECTFILE_NAMEFROMDBA_DATA_FILESWHERETABLESPACE_NAME='BOOKS';

FILE_NAME

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

/u01/oradata/orcl_st/books01.dbf

表空间成功创建,并且数据文件路径也被转换为我们指定的路径

此时如果你查看Alert日志文件,会发现其中记录下了类似这样的信息:

LOGSTDBYstmt:createtablespacebooksdatafile'/u01/oradata/orcl_pd/books01.dbf'size20m

LOGSTDBYstatus:ORA-16110:逻辑备用应用DDL的用户过程处理

LOGSTDBYid:XID0x0001.009.000000d1,hSCN0x0000.0012ec41,

lSCN0x0000.0012ec41,Thread1,RBA0x007f.0000079a.80,

txnCscn0x0000.0012ec43,PID5816,ORACLE.EXE(P004)

LOGSTDBYstmt:createtablespacebooksdatafile'/u01/oradata/orcl_st/books01.dbf'size20m

LOGSTDBYstatus:ORA-16202:跳过过程已请求替换语句

LOGSTDBYid:XID0x0001.009.000000d1,hSCN0x0000.0012ec41,

lSCN0x0000.0012ec41,Thread1,RBA0x007f.0000079a.80,

txnCscn0x0000.0012ec43,PID5816,ORACLE.EXE(P004)

createtablespacebooksdatafile'/u01/oradata/orcl_st/books01.dbf'size20m

Completed:createtablespacebooksdatafile'/u01/oradata/orcl_st/books01.dbf'size20m

LOGSTDBYstmt:createtablespacebooksdatafile'/u01/oradata/orcl_st/books01.dbf'size20m

LOGSTDBYstatus:ORA-16204:成功应用了DDL

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

6.1调整APPLIER进程数

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

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

SQL>SELECTCOUNT(*)ASIDLE_APPLIERFROMV$LOGSTDBY_PROCESSWHERETYPE='APPLIER'andstatus_code=16166;

IDLE_APPLIER

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

0

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

明:status_code=16166表示进程是空闲状态,因为stats_code=16166对应的状态说明列STATSORA-16116:noworkavailable

检查事务的应用情况:

SQL>SELECTNAME,VALUEFROMV$LOGSTDBY_STATSWHERENAMELIKE'transactions%';

NAMEVALUE

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

trans358

trans358

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

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

1停止逻辑Standby端的SQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

2)执行下列语句,调整APPLIER进程数为10

SQL>EXECUTEDBMS_LOGSTDBY.APPLY_SET('APPLY_SERVERS',10);

PL/SQLproceduresuccessfullycompleted.

3重新启动SQL应用:

JSSLDG>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

)查出的就是当前运行的APPLIER进程数:

SQL>SELECTCOUNT(0)FROMV$LOGSTDBY_PROCESSWHERETYPE='APPLIER';

COUNT(0)

----------

10

也可以通过V$LOGSTDBY_STATS视图查询,例如:

SQL>SELECT*FROMV$LOGSTDBY_STATSWHERENAME='numberofappliers';

NAMEVALUE

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

numbe10

6.2调整PREPARER进程数

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

先检查空闲PREPAPER进程数量:

SQL>SELECTCOUNT(*)ASIDLE_PREPARERFROMV$LOGSTDBY_PROCESS

WHERETYPE='PREPARER'andstatus_code=16166;

IDLE_PREPARER

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

0

说明:如果显示为0,别怕,也有可能是因为当前没什么新的REDO数据需要处理。

如果确实需要调整PREPAPER进程数量,可以按照下列步骤进行。

首先停止SQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

调整PREPAPER进程数量为4默认只有1PREPAPER进程):

SQL>EXECUTEDBMS_LOGSTDBY.APPLY_SET('PREPARE_SERVERS',4);

PL/SQLproceduresuccessfullycompleted.

重新启动SQL应用即可:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

当前启动的PREPAPER进程数,查询V$LOGSTDBY_STATS视图,例如:

SQL>SELECT*FROMV$LOGSTDBY_STATSWHERENAME='numberofpreparers';

NAMEVALUE

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

numbe4

6.3调整LCR使用的内存

LCR中保存的是转换后的块修改的记录,这部分数据保存在SGA.

查询当前LCR可用的最大内存:

SQL>SELECT*FROMV$LOGSTDBY_STATSWHERENAME='maximumSGAforLCRcache';

NAMEVALUE

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

maximumSGAforLCRcache30

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

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

1)首先还是需要停止SQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

Databasealtered.

2)调整内存大小为100M

SQL>EXECDBMS_LOGSTDBY.APPLY_SET('MAX_SGA',100);

PL/SQLproceduresuccessfullycompleted.

3最后重启SQL应用即可

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

Databasealtered.

6.4调整事务应用方式

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

1)停止SQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

2)允许事务不按照Primary的提交顺序应用:

SQL>EXECUTEDBMS_LOGSTDBY.APPLY_SET('PRESERVE_COMMIT_ORDER','FALSE');

3)重新启动SQL应用:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

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

1)先停止SQL应用:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

2)重置参数PRESERVE_COMMIT_ORDER的初始值:

SQL>EXECUTEDBMS_LOGSTDBY.APPLY_UNSET('PRESERVE_COMMIT_ORDER');

3)重新启动SQL应用:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

七.应用REDO数据到Standby数据库

1.物理Standby应用REDO数据

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

前台应用:

SQL>ALTERDATABASERECOVERMANAGEDSTANDBYDATABASE;

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

后台应用:

SQL>ALTERDATABASERECOVERMANAGEDSTANDBYDATABASEDISCONNECT;

这是现在比较通用的方式,语句执行完后,控制权自动返回到当前的命令行模式,REDO应用以后台进程运行。

启动实时应用,附加USINGCURRENTLOGFILE子句即可:

SQL>ALTERDATABASERECOVERMANAGEDSTANDBYDATABASEUSINGCURRENTLOGFILE;

如果要停止REDO应用,执行下列语句即可:

SQL>ALTERDATABASERECOVERMANAGEDSTANDBYDATABASECANCEL;

2.逻辑Standby应用REDO数据

SQL应用的原理是将接收到的REDO数据转换成SQL语句在逻辑Standby数据库端执行,因此逻辑Standby需要启动至OPEN状态。

1)启动SQL应用。逻辑Standby数据库启动SQL应用没有前、后台运行之说,语句执行完之后,控制权就会自动返回当前命令行窗口。要启动SQL应用,直接执行下列语句即可:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLY;

如果要启动实时应用,附加IMMEDIATE子句即可,例如:

SQL>ALTERDATABASESTARTLOGICALSTANDBYAPPLYIMMEDIATE;

2)停止SQL应用,如:

SQL>ALTERDATABASESTOPLOGICALSTANDBYAPPLY;

由于是执行SQL语句的方式应用REDO数据,因此上述语句的执行需要等待当前执行的SQL触发的事务结束,才能真正停止REDO应用的状态。

如果不考虑事务执行情况,马上停止REDO应用,可以通过下列的语句来完成:

SQL>ALTERDATABASEABORTLOGICALSTANDBYAPPLY;

注:整理自李丙洋《涂抹Oracle

<!--EndFragment-->

你可能感兴趣的:(oracle)