星期三 十月 23, 2013

Oracle 11g 新特性 – HM(Hang Manager)简介


在这篇文章中我们会对oracle 11g 新特性—hang 管理器(Hang Manager) 进行介绍。我们需要说明,HM 只在RAC 数据库中存在。



在我们诊断数据库问题的时候,经常会遇到一些数据库/进程 hang住的问题。对于hang的问题,一般来说,常见的原因有以下两种。


死锁(cycle)。对于这种hang, 除非循环被打破,问题会永远存在。


某个堵塞者(blocker) 进程在持有了某些资源后堵住了其他进程。当然,根据堵塞的情况,我们可以把blocker
分为直接堵塞进程(immediate blocker)和根堵塞进程(root blocker)。而root blocker 在通常情况下会处于两种状态。


2.1 根堵塞进程处于空闲状态,对于这种情况,终止这个进程能够解决问题。


2.2 根堵塞进程正在等待某些和数据库无关的资源(例如:等待I/O),对于这种情况,终止这个进程也许能解决问题。但是,从数据库的角度来讲,这已经超出了数据库的范畴。



而从数据库的角度来讲, oracle有几种死锁的发现机制。 在这篇文章中我们会介绍11g RAC的新特性 hang管理器。hang 管理器的基本步骤是。


1.分配一部分内存空间用于存放hang analyze dump 信息。


2.定期搜集hang analyze dump信息(本地和全局)


3. 分析搜集到的dump信息,并确认系统中是否存在hang


4. 利用分析的结果来解决hang问题。



接下来,我们对每个步骤进行具体的介绍。


步骤1: ORACLE 会分配一部分内存空间,我们称之为 hang analysis
cache
,用来存放搜集的hang analyze dump i信息。这部分内存空间在每个节点的数据库实例上都存在。


步骤2oracle 会定期搜集hang
analyze
信息,由于,HM特性是针对RAC数据库的特性,hang analyze的级别会包括本地和全局。另外,负责搜集这些dump 信息的后台进程是DIA0(这个进程从11g才被介绍)。默认情况下每3秒钟搜集本地级别hang analyze dump, 10 秒搜集全局级别hang analyze dump


步骤3:因为,每个节点都会搜集hang
analyze dump
信息,那么,意味着每个实例都会拥有自己的DIA0进程,负责完成本地的hang 分析。但是,对于RAC数据库,很多hang的情况会包含多个实例的进程。所以,我们需要一个实例上的DIA0 进程作为master,来对多个实例搜集到的信息进行分析。对于11g版本,节点号最小的实例的DIA0进程会成为HMmaster进程。当然,在实例级别发生了重新配置后,主(masterDIA0 进程会重新在存在的实例中重新被选举出来。



对于hang的问题,HM采用以下的机制来进行检测,当HM分析过几个hang analyze dump(每30秒进行一次分析,至少经过三次分析)后,就会发现有一些进程之间存在着等待关系(我们可以称之为open chain),而且在这段时间之内没有任何的改变(例如,一直等待相同的等待事件),那么,我们就可以怀疑,这些进程之间出现了hang的情况。而在进一步的验证之后,的确发现这些进程之间存在着等待关系,那么就会找到这个等待链(open chain)的根阻塞进程,并尝试通过终止阻塞进程的方式来解决这个hang.当然,对于死锁(dead lock)这种情况,我们采用的方式是,终止等待环中的一个进程。下面的图形说明了以上的基本逻辑。




步骤4: 在确认hang的确发生之后,根据hang的类型选择对应的解决方案。对于HM 来说,如果这个hang线管的进程满足以下条件之一,那么HM就无法解决这个hang.


1. 除数据库以外的其他层面的进程也和这个hang相关,例如:asm实例的进程。


2. 是由于用户应用层面导致的,例如:TX锁。


3. 并行查询


4. 需要用户手动干预。例如:阻塞进程在等待“log file switch ”(这种等待很可能是由于归档目录对应的filesystem空间不足导致的。即使HM中知道了阻塞进程,hang的情况也无法得到解决)。



如果,hangHM无法解决的类型,那么HM会继续跟踪这个问题。
而对于HM能够解决的问题,其解决的办法就是终止根阻塞进程。但是,如果这个阻塞进程是oracle 的主要后台进程,终止它就会导致实例crash。所以,HM在解决hang的时候,也存在解决范围。这个范围是由隐含参数"_hang_resolution_scope" 控制的,这个参数可以有三个值off(默认值,也就是说HM不会去解决hang)process(允许HM终止阻塞进程,如果该进程不是主要的后台进程),instance(允许HM终止阻塞进程,即使该进程是主要的后台进程。终止该进程会导致实例终止)。



最后,我们对和HM 相关的一些参数和trace 文件进行简单的介绍。


参数:


_hang_resolution=TRUE 或者 FALSE。这个参数用于控制HM是否解决hang


_hang_resolution_scope=OFF,PORCESS或者 INSTANCE。这个参数用于控制HM解决问题的范围。


_hang_detection= <number> HM检测hang的时间间隔,默认值为30(秒)。



参与此主题的后续讨论,可以访问我们的中文社区,跟帖“Oracle 11g 新特性 – HM(Hang Manager)简介"

12c新特性 - Active Data Guard Far Sync


概述

================

Active Data Guard Far Sync是Oracle 12c的新功能(也称为Far Sync Standby),Far Sync功能的实现是通过在距离主库(Primary Database)相对较近的地点配置Far Sync实例,主库(Primary Database) 同步(synchronous)传输redo到Far Sync实例,然后Far Sync实例再将redo异步(asynchronous)传输到终端备库(Standby Database)。这样既可以保证零数据丢失又可以降低主库压力。Far Sync实例只有密码文件,init参数文件和控制文件,而没有数据文件。

如果redo 传输采用Maximum Availability模式,我们可以在距离生产中心(Primary Database)相对较近的地点配置Far Sync实例,主库(Primary Database)同步(synchronous)传输redo到Far Sync实例,保证零数据丢失(zero data loss),同时主库和Far Sync距离较近,网络延时很小,因此对主库性能影响很小。然后Far Sync实例再将redo异步(asynchronous)发送到终端备库(Standby Database)。

如果redo 传输采用Maximum Performance模式,我们可以在距离生产中心(Primary Database)相对较近的地点配置Far Sync实例,主库(Primary Database) 异步传输redo到Far Sync实例,然后Far Sync实例再负责传输redo到其他多个终端备库(Standby Database)。这样可以减少主库向多个终端备库(Standby Database)传输redo的压力(offload)。

Far Sync配置对于Data Guard 角色转换(role transitions)是透明的,即switchover/failover命令方式与12c之前相同。

考虑到可能发生Data Guard 角色转换,即switchover/failover,可以在距离备库较近的地方也配置Far Sync实例,这个Far Sync实例只有在当前的备库切换为主库后才启用。

考虑到Far Sync实例的单点故障,可以在距离主库交近的地点配置2个Far Sync实例,起到备用的作用。

本文重点是测试Far Sync安装配置。

Far Sync示意图

================

创建配置Far Sync

================

1. 创建Data Guard,方法与11.2相同,详细过程参考《Active Database Duplication for A standby database

2. 创建配置Far Sync实例,Far Sync实例只有密码文件,init参数文件和控制文件,而没有数据文件。

创建Far Sync实例的控制文件,在主库执行:

SQL> ALTER DATABASE CREATE FAR SYNC INSTANCE CONTROLFILE AS '/tmp/controlfs01.ctl';

3. 设置主库redo同步传输到Far Sync实例,修改主库LOG_ARCHIVE_DEST_2参数:

LOG_ARCHIVE_DEST_2='SERVICE=dg12cfs SYNC AFFIRM MAX_FAILURE=1 ALTERNATE=LOG_ARCHIVE_DEST_3

VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE) DB_UNIQUE_NAME=dg12cfs'

4. 设置Far Sync实例异步传输redo到备库,修改Far Sync实例LOG_ARCHIVE_DEST_2参数:

LOG_ARCHIVE_DEST_2='SERVICE=dg12cs ASYNC

VALID_FOR=(STANDBY_LOGFILES,STANDBY_ROLE) DB_UNIQUE_NAME=dg12cs'

5. 为了解决Far Sync实例的单点故障,可以在距离主库较近的地点配置2个Far Sync实例。

6. 创建完成后确认:

SQL> select * from  V$DATAGUARD_CONFIG;

DB_UNIQUE_NAME       PARENT_DBUN       DEST_ROLE         CURRENT_SCN     CON_ID

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

dg12cfs                        dg12cp          FAR SYNC INSTANCE      682995          0

dg12cs                         dg12cfs         PHYSICAL STANDBY       682995          0

dg12cp                        NONE             PRIMARY DATABASE      683138          0

详细配置过程和测试案例请参考附件:Oracle_12c_Active_Data_Guard_Far_Sync_v1.pdf

星期四 八月 01, 2013

11gR2新特性---gipc守护进程


在这篇文章中,我们会对11gR2 新的守护进程gipcd(资源名称ora.gipcd)进行介绍,其中包括gipc的功能,启动顺序和一些基本的测试。


我们知道,对于oracle集群来说,集群私网是非常重要的,无论是集群的网络心跳,节点间通信还是数据库的cache fusion 都需要通过私网来实现。所以,我们会在很多的文档中都看到oracle集群的私网要稳定而且高速,要使用交换机,不能使用直连线(详细的原因可以参考Note 220970.1:RAC: Frequently Asked Questions,本文不作过多的解释)。如果可能的话,对集群私网网卡配置冗余/负载均衡,以确保集群私网的稳定和高效。 但是,在10gR2 11gR1的版本上,这需要借助第三方软件来实现,例如:Linux bonding, AIX EtherChannel, HP-UX APA 等。大部分的网卡聚合软件都会将多个网络接口聚合成为一个逻辑接口(当然,不同的聚合软件会有不同的实现方式,在这里不做讨论)。在安装和配置10g 11.1 版本的集群时,如果您对集群私网的网络接口进行了聚合(冗余或负载均衡),只需要将聚合后的网卡名称和对应的subnet信息告诉集群,换句话说,网卡聚合对oracle集群来说是透明的。但是,这也会给集群带来一些不稳定性,如果网卡聚合配置不正确,当被聚合的网卡之一出现问题时,集群很可能认为私网出现问题而导致很严重的问题,例如:节点重启,实例重启等。


正是由于以上的问题,从11gR2开始(具体点说,从11.2.0.2开始),oracle决定由集群自己来管理私网网卡,集群新特性gipc(Grid
IPC)
被介绍,这个新特性以守护进程gipcd.bin的形式存在于集群中,主要的功能有。


1. 当集群启动时,发现集群的私网网卡。当然,基于之前文章的介绍,集群私网的信息是从gpnp profile中获得的。并对发现的私网接口进行检查。


2. 利用之前发现的私网网卡,发现集群中的其他节点,并和其他节点的私网网卡建立联系。


3. 如果集群配置了多块私网网卡,当某个节点的某一个/几个私网网卡出现问题时,离线有问题的私网,并通知其他节点。


当然,oracle依然支持使用第三方网卡聚合软件对集群私网进行冗余/负载均衡配置,但是,这显然不是个好主意。


另外,在和一些同事和朋友探讨时也发现,很多朋友对gipc
HAIP的概念和功能还不是很清楚,在这里也做一些解释。我们知道,集群私网主要负责两类数据的通信。第一种:集群层面的数据通信,例如:ocssd.bin网络心跳,crsd.bin之间的通信等;第二种:oracle RAC 通信,例如:ASM 实例间的通信,数据库实例间的通信等。而且,第二种数据通信的工作负载要远远大于第一种。gipc,作为管理集群私网的进程,它需要向集群中的其他组件提供集群的私网信息,但是这进程并不负责传递具体的信息,具体的信息,仍然由对应的进程自己传输,当然,这主要针对第一种数据通信。正是由于gipc的出现,oracle 集群具有了管理集群私网的能力,而且第二种信息工作负载又很大,同时集群管理的主要资源就是数据库,HAIP 应运而生,作为实现oracle RAC通信的高可用/负载均衡的实现方法,来完成集群第二种信息的传递。所以,很多时候,如果我们发现只是HAIP出现问题时,受影响的会是数据库实例和ASM实例,而集群层面(也就是NM层面)的一致性仍然能够保证,而且集群的成员也不会发生改变。对于HAIP,本文不作过多介绍,更多信息,请参考之前的文章 “Redundant Interconnect
with Highly Available IP (HAIP)
简介”。


接下来,我们通过集群的一些日志对之前的内容进行一些验证。


1.集群启动时的gipcd.log


2013-07-17
12:28:28.071: [ default][3041003216]gipcd START pid=22337 Oracle Grid IPC
Daemon


2013-07-17
12:28:28.072: [ GIPCD][3041003216]
gipcdMain: gipcd Started
<<<<<< gipcd守护进程被启动了。


……


2013-07-17
12:28:29.046: [ GPNP][3041003216]clsgpnp_getCachedProfileEx: [at clsgpnp.c:613] Result:
(26) CLSGPNP_NO_PROFILE. Can't get offline GPnP service profile: local gpnpd is
up and running. Use getProfile instead.


2013-07-17
12:28:29.046: [ GPNP][3041003216]clsgpnp_getCachedProfileEx: [at clsgpnp.c:623] Result:
(26) CLSGPNP_NO_PROFILE. Failed to get offline GPnP service profile.


2013-07-17
12:28:29.066: [ GPNP][3041003216]clsgpnpm_newWiredMsg: [at clsgpnpm.c:741] Msg-reply has
soap fault 10 (Operation returned Retry (error CLSGPNP_CALL_AGAIN)) [uri
"http://www.grid-pnp.org/2005/12/gpnp-errors#"]
<<<< gipcd 尝试访问gpnp profile但是没有成功。由于log是在GI启动时获取的,这部分信息可以忽略,因为原因是gpnpd还没有成功启动。


……


2013-07-17
12:28:39.342: [ CLSINET][3023027088] # 0 Interface
'eth1',ip='192.168.254.30',mac='00-0c-29-a8-14-65',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17
12:28:39.342: [ CLSINET][3023027088] # 1 Interface
'eth2',ip='192.168.254.31',mac='00-0c-29-a8-14-6f',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'
<<<<<
gipcd
发现了本地节点用于私网的网卡信息,在这个集群中有2块网卡作为集群的私网。


……


2013-07-17 12:28:39.344:
[GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local bootstrap
interface for node 'single1', haName 'gipcd_ha_name', inf
'mcast://230.0.1.0:42424/192.168.254.30'


2013-07-17
12:28:39.344: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local
interface for node 'single1', haName 'gipcd_ha_name', inf
'192.168.254.30:46782'


2013-07-17
12:28:39.345: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local
bootstrap interface for node 'single1', haName 'gipcd_ha_name', inf
'mcast://230.0.1.0:42424/192.168.254.31'


2013-07-17
12:28:39.345: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local
interface for node 'single1', haName 'gipcd_ha_name', inf
'192.168.254.31:39332' <<<<<<<
gipcd 用于集群数据通信(就是我们之前提到的第一种数据通信)的endpoint 已经产生。


……


2013-07-17
12:28:56.767: [GIPCHGEN][3023027088] gipchaNodeCreate: adding new node 0x9c107d8 { host 'single2', haName
'gipcd_ha_name', srcLuid 465fb26d-8b46eb95, dstLuid 00000000-00000000 numInf 0,
contigSeq 0, lastAck 0, lastValidAck 0, sendSeq [0 : 0], createTime 797327224,
flags 0x0 } <<<<<
远程节点被发现。


……


2013-07-17
12:28:58.415: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created
remote interface for node 'single2', haName 'gipcd_ha_name', inf
'udp://192.168.254.33:16663'


2013-07-17
12:28:58.415: [GIPCHGEN][3025128336] gipchaWorkerAttachInterface: Interface
attached inf 0x9c0bb60
{ host 'single2', haName 'gipcd_ha_name', local 0xb4c4e590, ip '192.168.254.33:16663', subnet
'192.168.254.0', mask '255.255.255.0', numRef 0, numFail 0, flags 0x6 }


2013-07-17
12:28:58.415: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created
remote interface for node 'single2', haName 'gipcd_ha_name', inf
'udp://192.168.254.32:17578'


2013-07-17
12:28:58.415: [GIPCHGEN][3025128336] gipchaWorkerAttachInterface: Interface
attached inf 0x9c0a900 { host 'single2', haName
'gipcd_ha_name', local 0xb4cb8eb8, ip '192.168.254.32:17578', subnet
'192.168.254.0', mask '255.255.255.0', numRef 0, numFail 0, flags 0x6 } <<<<<<
gipcd 发现了远程节点私网的网卡信息。


……


2013-07-17
12:29:36.120: [GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 0] eth1 - rank 99, avgms 6.326531 [ 257 / 250 / 245 ]


2013-07-17
12:29:36.120: [GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 1] eth2 - rank 99, avgms 5.182186 [ 259 / 250 / 247 ] <<<<<
gipcd 检查本地私网网卡状态。


……


 2. 当集���中的一个私网down掉时的gipcd.log


2013-07-17
13:23:20.346: [ CLSINET][3027229584] Returning NETDATA: 2 interfaces


2013-07-17
13:23:20.346: [ CLSINET][3027229584] # 0 Interface
'eth1',ip='192.168.254.30',mac='00-0c-29-a8-14-65',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17
13:23:20.346: [ CLSINET][3027229584] # 1 Interface
'eth2',ip='192.168.254.31',mac='00-0c-29-a8-14-6f',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17 13:23:20.359:
[GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 0] eth1 - rank 99, avgms 1.560694 [ 171 / 173 / 173 ]


2013-07-17
13:23:20.359: [GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 1] eth2 - rank 99, avgms 1.802326 [ 172 / 172 / 172 ] <<<<<<<<
gipcd 仍然在进行私网检查。


……


+++使用命令“ifconfig eth1 down”禁用集群中的一个私网网卡。


……


2013-07-17
13:23:44.397: [ CLSINET][3027229584] # 0 Interface
'eth2',ip='192.168.254.31',mac='00-0c-29-a8-14-6f',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17
13:23:44.397: [GIPCDMON][3027229584] gipcdMonitorUpdate: interface went down -
[ ip 192.168.254.30, subnet 192.168.254.0, mask 255.255.255.0 ]


2013-07-17
13:23:44.397: [GIPCDMON][3027229584] gipcdMonitorUpdate: msg sent to client
thread (([update(ip: 192.168.254.30, mask: 255.255.255.0, subnet
192.168.254.0), state(gipcdadapterstateDown)]))
<<<<<<<<
gipcd 发现私网eth1 down掉,同时向它的客户(例如:ocssd.bin)发送消息。


……


2013-07-17
13:23:44.426: [GIPCHGEN][3025128336] gipchaInterfaceDisable: disabling
interface 0xb4c4e590
{ host '', haName 'gipcd_ha_name', local (nil), ip '192.168.254.30', subnet
'192.168.254.0', mask '255.255.255.0', numRef 0, numFail 1, flags 0x1cd }


2013-07-17
13:23:44.428: [GIPCHGEN][3025128336] gipchaInterfaceDisable: disabling
interface 0x9c0bb60
{ host 'single2', haName 'gipcd_ha_name', local 0xb4c4e590, ip '192.168.254.33:16663', subnet
'192.168.254.0', mask '255.255.255.0', numRef 0, numFail 0, flags 0x86 }


2013-07-17
13:23:44.428: [GIPCHALO][3025128336] gipchaLowerCleanInterfaces: performing
cleanup of disabled interface 0x9c0bb60
{ host 'single2', haName 'gipcd_ha_name', local 0xb4c4e590, ip '192.168.254.33:16663', subnet
'192.168.254.0', mask '255.255.255.0', numRef 0, numFail 0, flags 0xa6 } <<<<<<<<
gipcd 开始清理本地私网eth1 的信息,同时也清理掉与之对应的远程节点私网的信息。


……


2013-07-17
13:24:08.747: [GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 0] eth2 - rank 99, avgms 1.955307 [ 204 / 181 / 179 ] <<<<<<<
gipcd 继续检查正常的私网网卡。



注意:在整个过程中,我们还会看到集群的一致性仍然能够保证,不会出现节点离开集群的现象。而且,我们还会看到原来运行在eth1上的HAIP,会failovereth2 上,与此同时,数据库和ASM实例一切正常。



3. 当网卡eht1恢复后。


++ 使用命令”ifconfig eth1 up”恢复网卡eth1


2013-07-17
13:36:31.260: [GIPCDMON][3027229584] gipcdMonitorUpdate: New Interface found -
[ ip 192.168.254.30, subnet 192.168.254.0, mask 255.255.255.0 ]


2013-07-17
13:36:31.260: [GIPCDMON][3027229584] gipcdMonitorUpdate: msg sent to client
thread (([update(ip: 192.168.254.30, mask: 255.255.255.0, subnet
192.168.254.0), state(gipcdadapterstateUp)])) <<<<<
gpicd 发现了新的私网网卡。


……


2013-07-17 13:36:31.471:
[GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local bootstrap
interface for node 'single1', haName 'gipcd_ha_name', inf
'mcast://230.0.1.0:42424/192.168.254.30'


2013-07-17
13:36:31.471: [GIPCHTHR][3025128336] gipchaWorkerUpdateInterface: created local
interface for node 'single1', haName 'gipcd_ha_name', inf
'192.168.254.30:55548' <<<<<<
本地的通信endpoint被建立。


……


2013-07-17
13:37:11.493: [ CLSINET][3027229584] Returning NETDATA: 2 interfaces


2013-07-17
13:37:11.493: [ CLSINET][3027229584] # 0 Interface
'eth1',ip='192.168.254.30',mac='00-0c-29-a8-14-65',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17
13:37:11.493: [ CLSINET][3027229584] # 1 Interface
'eth2',ip='192.168.254.31',mac='00-0c-29-a8-14-6f',mask='255.255.255.0',net='192.168.254.0',use='cluster_interconnect'


2013-07-17
13:37:11.510: [GIPCDMON][3027229584] gipcdMonitorSaveInfMetrics: inf[ 0] eth2 - rank 99, avgms 6.141304 [ 307 / 184 / 184 ] <<<<<<<<
<<<<<<<<
gipcd进行私网检查。


注意:在整个过程中,我们还会看到集群的一致性仍然能够保证,不会出现节点离开集群的现象。而且,我们还会看到之前failovereth2上的HAIP,会重新回到eth1 上,与此同时,数据库和ASM实例一切正常。



最后,我们需要强调的是,gipcd 虽然能够管理集群的私网,但是,如果私网网卡本身,或者节点间私网链路(或者性能)存在问题,gipcd仍然无法正常工作。另外,如果您在使用HAIP的同时,仍在使用了第三方的网卡聚合软件(例如:Linux bondingetherchannel等),最好使用最新版本的软件,并且确保配置正确。


希望以上的解释能够对大家了解11gR2 新的守护进程gipcd有些帮助,并且在处理相关问题的时候,能够保持正确的方向。


参与此主题的后续讨论,可以访问我们的中文社区,跟帖“共享:11gR2新特性---gipc守护进程"。

星期一 七月 29, 2013

11gR2新特性---Gpnp守护进程


在这篇文章中,我们会对11gR2 新的守护进程(资源名称ora.gpnpd)进行介绍,其中包含的gpnp的功能,启动顺序和基本的诊断方法。


我们知道,在10gR211gR1的版本中,当启动集群的时候,所有的配置信息都要从OCR进行读取,而OCR有存放在共享内存中,这样做实际上并不是很好,因为我们相当于把集群所有的配置信息都存放到了共享存储上,而一旦某个节点对共享存储的访问出现了问题,这个节点就不能加入集群,对集群的影响是很大的,所以,从11gR2开始,GI(Grid Infrastructure) 开始把集群的配置信息进行本地化,例如:
OLR
gpnp profile 被引入。随着我们将集群中重要的信息分别存放到了各个节点,我们也会发现,从11gR2开始,如果OCR出现了问题,仅仅是某些集群的资源(由CRSD管理的资源)会出现问题,而集群(cssd层面)仍然可以正常运行。


接下来,我们对gpnp profile gpnpd守护进程进行一些介绍。首先,gpnp profile(这是个xml文件,而对于gpnp wallet文件,我们并不做过多的介绍)用于存放构建集群的bootstrap 信息,或者可以称为构建集群的最基本的信息,其中包括,集群名称,集群GUID, ASM discovery string, 公网和私网信息等等。所以,当我们在启动集群的某一个节点时,需要读取这个文件(默认文件名为<gi_home>/gpnp/<node_name>/profiles/peer/profile.xml,从而获得构建集群的基本信息。另外,由于这个文件中保存的是整个集群的基本信息,所以这个文件在所有节点之间都应该是相同的。同时,我们还需要一个守护进程,也就是gpnpd.bin(资源名为 ora.gpnpd) 来对gpnp profile 进行维护。举个例子,一个3节点的集群,其中节点3由于一些问题暂时没有启动,而在此期间,集群的私网配置发生了改变,之后,节点3启动,在启动的过程中,节点3gpnpd进程需要和其他节点的gpnpd进程通信,获得最新版本的gpnp profile


下面,我们对 gpnpd守护进程的功能进行一些介绍。


1. 这个进程是由ohasd oraagent 负责管理的。


2. 通过gpnp wallet文件进行验证并负责读取gpnp prfofile。当然,如果gpnpd发现本地的gpnp profile 无法读取,会尝试从OLR的信息中重建gpnp profile


3. gpnp profile的客户(例如ocssd.bin)发布信息。


4. 发现集群中其他节点的gpnpd 守护进程,如果有需要,通过mdns 同步在节点间同步gpnp profile


5. 如果集群的配置发生改变,有必要的话,修改gpnp profile.


接下来,我们通过启动集群过程中的一段gpnpd.log来对以上的内容进行进一步的了解。


2013-07-26 21:31:44.208: [ default][4143449792]gpnpd
START pid=<xxxx> Oracle Grid Plug-and-Play Daemon <<<<<< gpnpd.bin
守护进程被启动。


……


2013-07-26 21:31:45.234: [ GPNP][4143449792]clsgpnpkwf_initwfloc: [at
clsgpnpkwf.c:399] Using FS Wallet Location : <gi_home>/gpnp/<node_name>/wallets/peer/
<<<<<<<<<< gpnp
wallet 文件被访问


……


2013-07-26 21:31:45.349: [ default][4143449792]GPNPD
started on node XXXXX.


2013-07-26 21:31:45.350: [ GPNP][4143449792]clsgpnpd_MainWork: [at
clsgpnpd.c:4836] --- Local best profile:


2013-07-26 21:31:45.350: [ GPNP][4143449792]clsgpnpd_MainWork:
<?xml version="1.0"
encoding="UTF-8"?><gpnp:GPnP-Profile Version[cont]


……


2013-07-26 21:31:45.350: [ GPNP][4143449792]clsgpnpd_MainWork:
usterName="XXXXXX"
PALocation=""><gpnp:Network-Profile><[cont]


2013-07-26 21:31:45.351: [ GPNP][4143449792]clsgpnpd_MainWork:
gpnp:HostNetwork id="gen" HostName="*"><gpnp:Network
id="net1" I[cont]


2013-07-26 21:31:45.351: [ GPNP][4143449792]clsgpnpd_MainWork:
P="XXX.XXX.XXX.XXX" Adapter="eth1"
Use="cluster_interconnect"/><gpn[cont]


2013-07-26 21:31:45.351: [ GPNP][4143449792]clsgpnpd_MainWork:
p:Network id="net2" IP="XXX.XXX.XXX.XXX "
Adapter="eth0" Use="public[cont]
<<<<<<<<<< gpnp pofile
被读取。


……


2013-07-26 21:31:46.162: [ GPNP][4143449792]clsgpnpdRCB: [at
clsgpnpd.c:3933] GPnPD endpoint url "mdns:gpnp._tcp://XXXXX:27230/agent=gpnpd,cname=xxxxx,host=xxxxx,pid=xxxx/gpnpd
h:****** c:*******" successfully advertised with RD <<<<<< gpnpd
通过mdns发布了本地节点的endpoint.


2013-07-26 21:31:51.375: [ GPNP][120384416]clsgpnp_profileCallUrlInt:
[at clsgpnp.c:2104] put-profile call to url "tcp://xxxxx:56182" disco
"mdns:service:gpnp._tcp.local.://xxxxxx:56182/agent=gpnpd,cname=xxxxxxxxx,guid=6de9b87c2edadf6fbf4bb1fcf61e2fa0,host=xxxxxxx,pid=xxxxxx/gpnpd
h:****c:****u:6de9b87c2edadf6fbf4bb1fcf61" [f=0 claimed- host:****
cname:****** seq:4 auth:CN=GPnP_peer] <<<<<<<<
同时,gpnpd也通过mdns,在网络中搜索其他的节点。如果,网络中有多个集群(版本为11gR2 或者12c,那么其他集群的节点也会被发现,但是,gpnpd会通过集群的GUID进行区分。


……


2013-07-26 21:32:00.954: [ GPNP][120384416]clsgpnp_profileCallUrlInt:
[at clsgpnp.c:2104] put-profile call to url "tcp://xxxxx:32774" disco
"mdns:service:gpnp._tcp.local.://xxxxxx:32774/agent=gpnpd,cname=xxxxxxxxx,host=xxxxxx,pid=8023/gpnpd
h:*** c:****" [f=0 claimed- host:**** cname:***** seq:4
auth:CN=GPnP_peer] <<<<<<<<<
集群的另外一个节点XXXXX被发现,gpnpd 确认是否有必要在两个节点间同步gpnp profile.


……


2013-07-26 21:32:06.625: [ GPNP][120384416]clsgpnpd_pushThread: [at
clsgpnpd.c:4770] START gpnpd start serving clients after profile updates <<<<<<<<<< push
thread
被启动。如果需要,这个线程负责把本地的gpnp profile发送给其他节点。


……


2013-07-26 21:32:55.562: [ GPNP][79473568]clsgpnp_ocrDetectThread: [at
clsgpnp0.c:4508] OCR client init SUCCEEDED. OCR shared cache is now available
<<<<< gpnpd
开始监控OCR cache以便在集群的配置信息发生改变,而且有必要更新gpnp profile时进行修改。


最后,我们对和gpnpd相关的问题的诊断进行简单的描述。


1. 如果问题是本地的gpnp无法启动,那么根据gpnp的启动过程,需要察看。


1.1 Gpnpd pid 文件是否存在而且可以被访问


1.2 mdnsd 是否启动


1.3 gpnp wallet 文件是否存在,gpnp profile是否能够被grid 用户访问。


1.4 两个节点之间的网络连接是否正常。


1.5 其他节点的gpnpd.bin 是否正常。因为,在启动本地gpnpd.bin之后,它需要和集群其他节点的gpnpd.bin进行通信,以便确认集群中最新的gpnp profile


2. gpnpd的问题也会导致其他依赖于gpnpd的资源无法启动,例如ocssd.bin,这个进程需要访问gpnp profile获取集群的基本信息,例如 VF的位置,集群私网信息等。


3. 如果我们发现问题是gpnp profile中的信息出现了错误,可以使用工具gpnptool 进行修正。


4.对于诊断gpnpd问题所需要的信息,一般是


4.1 gpnpd.log 这个日志能够告诉我们gpnpd 是否被启动,以及,启动过程已经到达了哪一步,问题是在哪里出现的。


4.2 命令”crsctl stat res –t -init”的输出,它可以告诉我们ora.gpnpd资源的状态,以及集群中其他init资源的状态。


4.3 mdnsd.log, 如果我们发���问题出现在mdns无法发现集群中的其他节点,那么,这个文件很有帮助。


4.4 OSW 报告,它能够告诉我们OS当时的负载状况,集群网络统计信息等等。



希望通过以上的介绍能够让大家了解11gR2 GI 中新的守护进程gpnpd的一些认识,并在工作中遇到相关的问题时,有所帮助。

星期二 六月 04, 2013

Oracle 11.2 RAC One Node配置与管理


1. 概述

  RAC One Node是11.2的新特性, 是RAC数据库中的一个实例运行在GRID集群中,并且可以实现failover。

  这个功能有些类似于我们以前俗称的"HA数据库" <HA - high availability>, "HA数据库"是利用其他厂商的集群软件来管理Oracle单机数据库,实现数据库的高可用。而RAC One Node是通过ORACLE 集群软件(GRID)来管理数据库,实现数据库可以在集群中节点上切换(failover/relocate),达到数据库高可用的特点。RAC One Node是完全由Oracle提供的一整套高可用的解决方案。

  在11.2之前,为了实现数据库的高可用<俗称"HA数据库">,通常的做法是将单机数据库部署在其他厂商集群环境中(比如 HP MC/SG, IBM HACMP 等)管理,来实现数据库的高可用。即单机数据库运行在主节点上,当主节点需要维护或者异常中断的情况下,通过厂商集群软件将服务IP资源组和数据文件资源组切换(failover)到备节点,将数据库在备用节点重新启动。这个过程我们一般称为cold failover,因为数据库在切换的过程中是先shutdown再open。

  RAC One Node的原理与以前的HA数据库不同,RAC One Node是基于RAC数据库,并且通过Oracle集群软件(GRID)管理实现只启动RAC数据库的一个实例,当运行实例的节点需要维护停机的情况下,可以通过online database relocation的方式将数据库实例切换到集群中的其他节点上运行。



2.  RAC One Node 特点

+ RAC One Node 数据库很容易转变成RAC数据库, 转变过程是online的,不需要停RAC One node数据库.

+ 在GRID环境中可以创建多个RAC One Node数据库,分别运行在不同的节点上,增强了硬件的利用率。

+ RAC One Node配置全部采用oracle产品,管理维护和故障排除也变的更加简单。

+ 如果当前运行节点需要维护(OS 打patch等)或者服务器资源不足等等,可以手动切换数据库(relocate)到备用服务器,采用online database relocation,可以减少业务中断时间(应用需要配置TAF).

+ 对比RAC数据库,RAC One Node 数据库在性能方面也有优势,比如减少了RAC实例之间消息/数据请求传输的时间以及GC等待时间。



3.  到目前为止RAC One Node 发展经历了2 个阶段,阶段一是11.2.0.1,阶段二是11.2.0.2及以后.在11.2.0.1版本上,运行脚本raconeinit.sh来配置RAC One,运行omotion 脚本来手动切换(relocate),但是到11.2.0.2及以后,安装配置集成在DBCA,切换动作也集成在srvctl命令中。



4. 参考文档:

http://docs.oracle.com/cd/E11882_01/rac.112/e16795/onenode.htm

-- 4 Administering Oracle RAC One Node

Oracle RACOne Node -- Changes in 11.2.0.2 (Doc ID 1232802.1)




RAC One Node 安装配置具体测试过程请下载附件:Oracle_11gR2_RAC_One_node_configure_and_admin(v0.2).pdf


参与此主题的后续讨论,可以访问我们的中文社区,跟帖"共享:Oracle RAC One Node VS "HA数据库"。 



星期四 四月 18, 2013

如何安装独立版的CHM(Oracle Cluster Health Monitor)

     Cluster Health Monitor(以下简称CHM)是一个Oracle提供的工具,用来自动收集操作系统的资源(CPU、内存、SWAP、进程、I/O以及网络等)的使用情况。相对于OSWatcher,CHM直接调用OS的API来降低开销,而OSWatcher则是直接调用UNIX命令;另外,CHM的实时性更强,每秒收集一次数据(在11.2.0.3,改为了5秒一次)。 OSWatcher的优点是可以用traceroute命令检测私网间的连通性,而且生成的数据的保留时间可以设置得很长。如果可以的话,最好是两个工具都安装。

     对于CHM的更多解释,请参考之前的一篇博客:
11gR2 新特性:Oracle Cluster Health Monitor(CHM)简介

    在这篇文章中主要介绍如何安装独立版的CHM。

    CHM会自动安装在下面的软件:
    11.2.0.2 及更高版本的 Oracle Grid Infrastructure for Linux (不包括Linux Itanium) 、Solaris (Sparc 64 和 x86-64)
    11.2.0.3 及更高版本 Oracle Grid Infrastructure for AIX 、 Windows (不包括Windows Itanium)。

      在11.2.0.2之前的集群(10.2到11.2.0.1),可以安装独立版的CHM。目前支持的平台有Linux x86 和Linux x86-64,还有32位的Windows Server 2003 SP 2。独立版的CHM并不一定要安装在集群环境,单机环境也可以使用:
     o 在Linux平台上运行独立版的CHM,要求Linux kernel在2.6.9或之上。另外,一定不能在已经自动安装了CHM的集群环境上再安装单机版的。
     o 可以创建一个新的操作系统用户或者用oracle用户来进行安装,这个用户在RAC的节点间要建立用户等效性。
     o 安装完成后的CHM位于/usr/lib/oracrf,而且在/etc/init.d/init.crfd建立一个init脚本,这样在服务器重启后,只要crf是enabled,就可以自动启动。
     o CHM的数据保存在一个BDB数据库中,这个数据库所在的目录可以在安装CHM的时候用“-b”来指定。


下面是在Linux平台上的10.2.0.4的双节点RAC安装CHM的过程。

1. 下载单机版的CHM:
http://www.oracle.com/technetwork/database/clustering/downloads/ipd-download-homepage-087212.html
下载文件后,仔细阅读附带的README.txt文件。

2. 确保安装CHM的用户配置了用户等效性,可以无需密码ssh到远程节点。

如果要创建独立的用户,请执行:
# useradd -d /opt/crfuser -s /bin/sh -g oinstall crfuser

然后针对这个用户配置ssh,请参考:http://fedoranews.org/dowen/sshkeys/

在本文的例子中用oracle用户来安装。

3. 在一个节点,用oracle用户来解压CHM:
[oracle@rac1 ~]$su - oracle
[oracle@rac1 ~]$mkdir /home/oracle/chm 《==所有节点都要创建
[oracle@rac1 ~]$cd /home/oracle/chm
[oracle@rac1 jane]$ ls
1554900.zip
[oracle@rac1 jane]$ unzip 1554900.zip

4. 在一个节点用oracle用户来安装CHM:

首先要在所有节点都创建存放CHM db的目录:
#mkdir /opt/oracrfdb 《==用root 用户

确定在所有节点都有一个属主为oracle的目录/home/oracle/chm
/home/oracle/chm这个目录是临时用的,安装完后会这个临时目录中的CHM文件会被删除,真正安装完成的CHM在/usr/lib/oracrf。

用oracle安装:

[root@rac1 install]# su - oracle
[oracle@rac1 ~]$ cd /home/oracle/chm/install
[oracle@rac1 chm]$ perl /home/oracle/chm/install/crfinst.pl -i rac1,rac2 -b /opt/oracrfdb -m rac1

BDB path provided is on a root FS. Do you want to continue (Y/n):
Y

Performing checks on nodes: "rac1 rac2" ...
Assigning rac2 as replica

Generating cluster wide configuration file...

Creating a bundle for remote nodes...

Installing on nodes "rac2 rac1" ...

Configuration complete on nodes "rac2 rac1" ...

Please run "$CRFPERLBIN /home/oracle/chm/install/crfinst.pl -f, optionally specifying BDB location

with -b <bdb location> as root on each node to complete the install process.

5. 用root运行脚本:
节点1:
[oracle@rac1 chm]$ su -
Password:
[root@rac1 ~]# perl /home/oracle/chm/install/crfinst.pl -f

Installation completed successfully at /usr/lib/oracrf...

节点2:
[root@rac2 oracle]# perl /home/oracle/chm/install/crfinst.pl -f

Installation completed successfully at /usr/lib/oracrf...

CHM已经在所有节点安装成功。

6. 在所有节点用root身份enable CHM,这样在主机重启后,可以自动启动crf:

节点1:
[root@rac1 ~]# /etc/init.d/init.crfd enable

节点2:
[root@rac2]# /etc/init.d/init.crfd enable

7. 检查CHM状态:
节点1:
[root@rac1 ~]# /etc/init.d/init.crfd status 《==所有进程都已启动

osysmond running with PID=27793.
ologgerd running with PID=27895.

oproxyd running with PID=27910.

[root@rac1 ~]# ps -ef|grep osysmond
root     13234 26646  0 19:01 pts/0    00:00:00 grep osysmond
root     27793 27713  1 18:22 ?        00:00:42 /usr/lib/oracrf/bin/osysmond
[root@rac1 ~]# ps -ef|grep ologgerd
root     13274 26646  0 19:01 pts/0    00:00:00 grep ologgerd
root     27895     1  0 18:22 ?        00:00:04 /usr/lib/oracrf/bin/ologgerd -M -d /opt/oracrfdb
[root@rac1 ~]# ps -ef|grep oproxyd
root     13388 26646  0 19:01 pts/0    00:00:00 grep oproxyd
oracle   27910     1  0 18:22 ?        00:00:00 /usr/lib/oracrf/bin/oproxyd

节点2:
[root@rac2 oracle]# /etc/init.d/init.crfd status《==所有进程都已启动

osysmond running with PID=18321.
ologgerd running with PID=18455.

oproxyd running with PID=18479.

[root@rac2 oracle]# ps -ef|grep osysmond
root     18321 18234  1 18:49 ?        00:00:03 /usr/lib/oracrf/bin/osysmond
root     20065  4162  0 18:53 pts/0    00:00:00 grep osysmond
[root@rac2 oracle]# ps -ef|grep ologgerd
root     18455     1  1 18:49 ?        00:00:02 /usr/lib/oracrf/bin/ologgerd -m rac1 -r -d

/opt/oracrfdb
root     20086  4162  0 18:53 pts/0    00:00:00 grep ologgerd
[root@rac2 oracle]# ps -ef|grep oproxyd
oracle   18479     1  0 18:49 ?        00:00:00 /usr/lib/oracrf/bin/oproxyd
root     20113  4162  0 18:53 pts/0    00:00:00 grep oproxyd

8. 查看CHM的DB所在的目录:
节点1:
[root@rac1 chm]# ls -l  /opt/oracrfdb
total 92652
-rw-r----- 1 root root    643072 Mar 26 19:23 crfalert.bdb
-rw-r----- 1 root root  57147392 Mar 26 19:24 crfclust.bdb
-rw-r----- 1 root root      8192 Mar 26 18:58 crfconn.bdb
-rw-r----- 1 root root    823296 Mar 26 19:23 crfcpu.bdb
-rw-r----- 1 root root    548864 Mar 26 19:23 crfhosts.bdb
-rw-r----- 1 root root    925696 Mar 26 19:23 crfloclts.bdb
-rw-r----- 1 root root    487424 Mar 26 19:23 crfts.bdb
-rw-r----- 1 root root     24576 Mar 26 18:22 __db.001
-rw-r----- 1 root root    319488 Mar 26 18:22 __db.002
-rw-r----- 1 root root   2629632 Mar 26 18:22 __db.003
-rw-r----- 1 root root   2162688 Mar 26 18:22 __db.004
-rw-r----- 1 root root    778240 Mar 26 18:22 __db.005
-rw-r----- 1 root root     49152 Mar 26 18:22 __db.006
-rw-r----- 1 root root  16777216 Mar 26 19:19 log.0000000006
-rw-r----- 1 root root  16777216 Mar 26 19:23 log.0000000007
-rw-r--r-- 1 root root 120000000 Mar 26 18:22 rac1.ldb 《==========

节点2:
[root@rac2 chm]# ls -l  /opt/oracrfdb
total 92636
-rw-r----- 1 root root    397312 Mar 26 19:15 crfalert.bdb
-rw-r----- 1 root root  64159744 Mar 26 19:15 crfclust.bdb
-rw-r----- 1 root root    577536 Mar 26 19:15 crfcpu.bdb
-rw-r----- 1 root root    372736 Mar 26 19:15 crfhosts.bdb
-rw-r----- 1 root root   1011712 Mar 26 19:15 crfloclts.bdb
-rw-r----- 1 root root      8192 Mar 26 19:15 crfrep.bdb
-rw-r----- 1 root root    532480 Mar 26 19:15 crfts.bdb
-rw-r----- 1 root root     24576 Mar 26 18:49 __db.001
-rw-r----- 1 root root    319488 Mar 26 18:49 __db.002
-rw-r----- 1 root root   2629632 Mar 26 18:49 __db.003
-rw-r----- 1 root root   2162688 Mar 26 18:49 __db.004
-rw-r----- 1 root root    778240 Mar 26 18:49 __db.005
-rw-r----- 1 root root     49152 Mar 26 18:49 __db.006
-rw-r----- 1 root root  16777216 Mar 26 19:11 log.0000000006
-rw-r----- 1 root root  16777216 Mar 26 19:15 log.0000000007
-rw-r--r-- 1 root root 120000000 Mar 26 18:49 rac2.ldb 《==========
-rw-r----- 1 root root      8192 Mar 26 19:15 repdhosts.bdb

如何卸载单机版的CHM:

在所有RAC节点分别执行:

1. 用root用户disable CHM:
# /etc/init.d/init.crfd disable

2. 卸载CHM:
/usr/lib/oracrf/install/crfinst.pl -d

3. 手工删除CHM存放数据用的BDB(这个库的地址在安装时指定���。

4. 如果卸载后/usr/lib/oracrf仍然存在,可以手工删除这个目录。

如何使用单机版的CHM来收集性能数据:

方法1:
$oclumon dumpnodeview -allnodes -v -s "2013-03-26 18:00:00" -e "2013-03-26 21:10:00" > /tmp/chm1.txt

方法2:
在使用diagcollection.pl收集数据时,crshome 需要指定CHM的目录而不是CRS的目录:
# /usr/lib/oracrf/bin/diagcollection.pl --collect --crshome /usr/lib/oracrf --chmos --incidenttime

03/26/201312:00:00 --incidentduration 00:05

否则可能会报错:
# /usr/lib/oracrf/bin/diagcollection.pl --collect --crshome /oracle/app/product/10.2.0/crs_1 --chmos --

incidenttime 03/24/201325:00:00 --incidentduration 00:40
Production Copyright 2004, 2010, Oracle.  All rights reserved
Cluster Ready Services (CRS) diagnostic collection tool
Cannot parse master from output: sh: /oracle/app/product/10.2.0/crs_1/bin/oclumon: No such file or directory
diagcollection.pl

星期二 三月 05, 2013

11g Nested Loop Join的改变

11g中对Nested Loop Join有了一些改变,使用了新的实现方法来减少物理I/O的总体延迟:
官方在线文档在这里:
ttp://docs.oracle.com/cd/E11882_01/server.112/e16638/optimops.htm#PFGRF94642
对于一个示例SQL:
SELECT e.first_name, e.last_name, e.salary, d.department_name
    FROM hr.employees e, hr.departments d
    WHERE d.department_name IN ('Marketing', 'Sales')
      AND e.department_id = d.department_id;

11g以前(比如10g)的执行计划是这样:
-------------------------------------------------------------------------------------------------
| Id  | Operation                   | Name              | Rows  | Bytes | Cost (%CPU)| Time     |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT            |                   |    19 |   722 |     3  (0)| 00:00:01 |
|   1 |  TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |    10 |   220 |     1  (0)| 00:00:01 |
|   2 |   NESTED LOOPS              |                   |    19 |   722 |     3  (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL        | DEPARTMENTS       |     2 |    32 |     2  (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN         | EMP_DEPARTMENT_IX |    10 |       |     0  (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
   4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID" )

11g是这样:
------------------------------------------------------------------------------------------------
| Id  | Operation                    | Name              | Rows  | Bytes | Cost(%CPU)| Time      |
-------------------------------------------------------------------------------------------------
|   0 | SELECT STATEMENT             |                   |    19 |   722 |     3   (0)| 00:00:01 |
|   1 |  NESTED LOOPS                |                   |       |       |            |          |
|   2 |   NESTED LOOPS               |                   |    19 |   722 |     3   (0)| 00:00:01 |
|*  3 |    TABLE ACCESS FULL         | DEPARTMENTS       |     2 |    32 |     2   (0)| 00:00:01 |
|*  4 |    INDEX RANGE SCAN          | EMP_DEPARTMENT_IX |    10 |       |     0   (0)| 00:00:01 |
|   5 |   TABLE ACCESS BY INDEX ROWID| EMPLOYEES         |    10 |   220 |     1   (0)| 00:00:01 |
-------------------------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   3 - filter("D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales')
   4 - access("E"."DEPARTMENT_ID"="D"."DEPARTMENT_ID" )

并且提到了:Oracle Database 11g会将多个物理I/O请求合并,用一个总的向量I/O来处理,而不是一次处理一个。

那么,实际运行时Oracle究竟做了哪些改变呢?
我在AIX 6.1和linux上分别做了测试,来研究两个问题:
1)这个额外的NESTED LOOPS步骤,究竟有哪些改变?
2)什么是向量I/O?

10g在AIX上的10046 trace是这样:

10046 trace 10.2.0.5 on AIX 6.1:
---------------------------------------
WAIT #1: nam='db file scattered read' ela= 6907 file#=5 block#=20 blocks=5 obj#=-2147482976 tim=395875491122   <======obj#=-2147482976:DEPARTMENTS table Full scan  
...
WAIT #4: nam='db file sequential read' ela= 12942 file#=4 block#=84 blocks=1 obj#=-2147482977 tim=395875507033  <======obj#=-2147482977:EMP_DEPARTMENT_IX index branch block
WAIT #4: nam='db file sequential read' ela= 16 file#=4 block#=625 blocks=1 obj#=-2147482977 tim=395875507110    <======obj#=-2147482977:EMP_DEPARTMENT_IX index branch block
...
WAIT #4: nam='db file sequential read' ela= 14 file#=4 block#=5158 blocks=1 obj#=-2147482977 tim=395875507334   <======obj#=-2147482977:EMP_DEPARTMENT_IX index leaf block
WAIT #4: nam='db file sequential read' ela= 5071 file#=5 block#=12 blocks=1 obj#=-2147482978 tim=395875512477   <======obj#=-2147482978:EMPLOYEES table access by row id
WAIT #4: nam='db file sequential read' ela= 398 file#=5 block#=13 blocks=1 obj#=-2147482978 tim=395875512959    <======obj#=-2147482978:EMPLOYEES table access by row id
...

Nested Loop 11g之前的实现步骤是这样的:
a)全表扫描内部表DEPARTMENTS(可能使用部分过滤条件)
b)使用得到的数据关联外部表的索引,读取索引EMP_DEPARTMENT_IX枝节点(branch block)信息,
比如在这个例子里面,D"."DEPARTMENT_NAME"='Marketing' OR "D"."DEPARTMENT_NAME"='Sales',对应的DEPARTMENT_ID分别是20和80:
20    Marketing
80    Sales

在这一步,Oracle会获取哪些叶子节点(leaf block)才会包含有DEPARTMENT_ID=20或者80的ROWID,注意,它得到的只是叶子节点的block id,而没有真正获得叶子节点中存储的表上的ROWID。
也就是说,在这一步,它还没有读取叶子节点block,但是它已经拿到了所有叶子节点的block_id,作为中间结果(interim result),它实际已经获得了完整的结果集,
只不过这个结果集还在叶子节点存储的ROWID指向的表中的block上,也就是指向指针的指针:
叶子节点block_id => 叶子节点(ROWID) =>表block

c)根据叶子节点block_id读取叶子节点,以得到表ROWID,再读取表block.
这一步是读取一个叶子block,再读取多个表block,而不是一次取出全部叶子block,再一起读取表block。
因为不同叶子节点中存放的ROWID指向的表block可能是相同的,这样做可能提交了重复I/O请求。

11g的改变我猜测应该是把所有叶子节点读出来,再用一个大向量提交所有的表block I/O请求,也就是这个额外的NESTED LOOPS步骤。
但是实际测试的结果出人意料:

10046 trace 11.2.0.2 on AIX 6.1
---------------------------------------
WAIT #4574448288: nam='db file scattered read' ela= 3216 file#=5 block#=139 blocks=5 obj#=76651 tim=314602694473   <======obj#=76651:DEPARTMENTS Full scan
...
WAIT #4573144808: nam='db file sequential read' ela= 10457 file#=4 block#=171 blocks=1 obj#=76650 tim=314602714531 <======obj#=76650:EMP_DEPARTMENT_IX index branch block
WAIT #4573144808: nam='db file sequential read' ela= 9882 file#=4 block#=760 blocks=1 obj#=76650 tim=314602724535
...

WAIT #4573144808: nam='db file sequential read' ela= 4484 file#=4 block#=5255 blocks=1 obj#=76650 tim=314602744557 <======obj#=76650:EMP_DEPARTMENT_IX index leaf block
WAIT #4573144808: nam='db file sequential read' ela= 5378 file#=5 block#=131 blocks=1 obj#=76649 tim=314602750018  <======obj#=76649:EMPLOYEES table access by row id
...
WAIT #4573144808: nam='db file sequential read' ela= 9959 file#=4 block#=271 blocks=1 obj#=76650 tim=314602970033  <======obj#=76650:EMP_DEPARTMENT_IX index leaf block
WAIT #4573144808: nam='db file sequential read' ela= 15470 file#=5 block#=194 blocks=1 obj#=76649 tim=314602985572 <======obj#=76649:EMPLOYEES table access by row id
WAIT #4573144808: nam='db file sequential read' ela= 3234 file#=5 block#=195 blocks=1 obj#=76649 tim=314602988952  <======obj#=76649:EMPLOYEES table access by row id

从10046 trace看不出任何区别,取了truss才看出来差别在操作系统IO调用函数上:

10.2.0.5
------------
3014728:    26083579: kpread(12, 0x07000000128BA000, 8192, 0x000000000284C000, 0x0FFFFFFFFFFE7630) = 8192 <======12 users01.dbf INDEX EMP_DEPARTMENT_IX
3014728:    26083579: kpread(10, 0x0700000016622000, 8192, 0x0000000000018000, 0x0FFFFFFFFFFE7D30) = 8192 <======10 example01.dbf TABLE EMPLOYEES
3014728:    26083579: kpread(10, 0x0700000011AC8000, 8192, 0x000000000001A000, 0x0FFFFFFFFFFE7D30) = 8192 <======10 example01.dbf TABLE EMPLOYEES
3014728:    26083579: kpread(10, 0x0700000017578000, 8192, 0x000000000001E000, 0x0FFFFFFFFFFE7D30) = 8192 <======10 example01.dbf TABLE EMPLOYEES

<=========10.2.0.5上中规中矩,每个'db file sequential read'都由单个kpread提交。

11.2.0.2
-------------
7995454:    23658739: kpread(10, 0x070000000B77E000, 8192, 0x000000000021E000, 0x0700000018836A00) = 8192
<======10 users01.dbf INDEX EMP_DEPARTMENT_IX, 1 block
7995454:    23658739: kpread(10, 0x070000000CA16000, 8192, 0x00000000003EC000, 0x0700000018836A00) = 8192
<======10 users01.dbf INDEX EMP_DEPARTMENT_IX, 1 block
7995454:    23658739: listio64(0x0000000010000004, 0x000000000FFFFFFF, 0x00000000FFFC8890, 0x00000000000000FF, 0x0000000000000000, 0x0000000000000000, 0x0FFFFFFFFFF5F7B0, 0x00000000000000FE) = 0x0000000000000000
7995454:    23658739: aio_nwait64(0x0000000000001000, 0x00000000000000FF, 0x0FFFFFFFFFFD8890, 0x900000000000D032, 0x0000000000000000, 0x00000000000001A8, 0x0000000000000000, 0x0000000000000000) = 0x00000000000000FF
...
7995454:    23658739: kpread(10, 0x070000000FC7A000, 8192, 0x00000000004BA000, 0x0700000018836A00) = 8192
7995454:    23658739: listio64(0x0000000010000004, 0x000000000FFFFFFF, 0x00000000FFFC8890, 0x00000000000000FF, 0x0000000000000000, 0x0000000000000000, 0x0FFFFFFFFFF5F7B0, 0x00000000000000FE) = 0x0000000000000000
7995454:    23658739: aio_nwait64(0x0000000000001000, 0x00000000000000FF, 0x0FFFFFFFFFFD8890, 0x900000000000D032, 0x0000000000000000, 0x0000000000000164, 0x0000000000000000, 0x0000000000000000) = 0x00000000000000FF
...
<=========11.2.0.2上Index节点读取由单个kpread提交,表的数据读取由listio64提交,并用aio_nwait64等待返回结果。
但是仍然不是读取完全部ROWID之后统一提交,而是一个索引叶子block对应一次listio64.
listio64是API接口,操作系统上man lio_listio可以查到类似的解释。

man lio_listio

lio_listio or lio_listio64 Subroutine

       The lio_listio or lio_listio64 subroutine includes information for the
       POSIX AIO lio_listio subroutine (as defined in the IEEE std 1003.1-
       2001), and the Legacy AIO lio_listio subroutine.

       POSIX AIO lio_listio Subroutine

Purpose

       Initiates a list of asynchronous I/O requests with a single call.

Description

       The lio_listio subroutine initiates a list of I/O requests with a
       single function call.

Parameters
       mode
            Determines whether the subroutine returns when the I/O operations
            are completed, or as soon as the operations are queued.
       list
            An array of pointers to aio control structures defined in the
            aio.h file.
       nent
            Specifies the length of the array.
       sig
            Determines when asynchronous notification occurs.

以上正好解释了第2个问题,什么是向量I/O,向量I/O是将多个I/O请求存储在一个结构(structure)中,并用一个请求提交。
它依赖于不同的操作系统接口函数来实现。

综上所述,Oracle 11g关于Nested Loop Join的改变,并不在Join顺序或者中间结果集的存放方法上,而仅仅是在操作系统函数调用上封装了一层,把以前依次提交的多个I/O请求封装到了一个结构体中,并一次提交这些请求。
比较与线性I/O的实现,向量I/O的实现除了可以减少系统调用的次数,还可以经内部的优化提供性能的改善。

星期四 二月 28, 2013

RAC数据库后台进程介绍

   在RAC数据库上会比单实例数据库多一些进程,这些进程是RAC特有的,为了实现集群数据库功能而设置的。

10g RAC特有进程:
$ ps -ef|grep ora_
oracle    4721     1  0 Feb26 ?        00:00:00 ora_diag_ONEPIECE1
oracle    4725     1  0 Feb26 ?        00:02:26 ora_lmon_ONEPIECE1
oracle    4727     1  0 Feb26 ?        00:00:02 ora_lmd0_ONEPIECE1
oracle    4729     1  0 Feb26 ?        00:00:01 ora_lms0_ONEPIECE1
oracle    4733     1  0 Feb26 ?        00:00:01 ora_lms1_ONEPIECE1
oracle    4761     1  0 Feb26 ?        00:00:07 ora_lck0_ONEPIECE1
oracle    4772     1  0 Feb26 ?        00:00:00 ora_asmb_ONEPIECE1
oracle    4776     1  0 Feb26 ?        00:00:00 ora_rbal_ONEPIECE1
oracle    4840     1  0 Feb26 ?        00:00:00 ora_o001_ONEPIECE1

11g RAC特有进程:
$ ps -ef|grep ora_
oracle     426     1  0 Feb27 ?        00:00:08 ora_o000_RAC11G21
oracle    9082     1  0 Feb25 ?        00:01:09 ora_diag_RAC11G21
oracle    9086     1  0 Feb25 ?        00:00:27 ora_ping_RAC11G21
oracle    9088     1  0 Feb25 ?        00:00:06 ora_acms_RAC11G21
oracle    9092     1  0 Feb25 ?        00:05:27 ora_lmon_RAC11G21
oracle    9094     1  0 Feb25 ?        00:01:32 ora_lmd0_RAC11G21
oracle    9096     1  0 Feb25 ?        00:02:07 ora_lms0_RAC11G21
oracle    9100     1  0 Feb25 ?        00:00:06 ora_rms0_RAC11G21
oracle    9102     1  0 Feb25 ?        00:00:14 ora_lmhb_RAC11G21
oracle    9116     1  0 Feb25 ?        00:00:09 ora_rbal_RAC11G21
oracle    9118     1  0 Feb25 ?        00:00:05 ora_asmb_RAC11G21
oracle    9136     1  0 Feb25 ?        00:04:25 ora_lck0_RAC11G21
oracle    9138     1  0 Feb25 ?        00:00:14 ora_rsmn_RAC11G21
oracle    9295     1  0 Feb25 ?        00:00:07 ora_gtx0_RAC11G21
oracle    9297     1  0 Feb25 ?        00:00:07 ora_rcbg_RAC11G21

这篇文章会对这些RAC特有的进程做一些介绍。

LMD: Global Enqueue Service Daemon。LMD 进程主要处理从远程节点发出的资源请求。大概过程如下:
+ 一个连接发出了global enqueue 请求
+ 这个请求会被发给本节点的LMD0进程
+ 这个前台进程会处于等待状态
+ LMD0会找到这个资源的master节点是谁
+ LMD0会把这个请求发送给master节点
+ 如果需要的话,master节点会增加一个新的master资源
+ 这时从master节点可以获知谁是owner, waiter
+ 当这个资源被grant给requestor后, master节点的LMD0进程会告知requestor节点的LMD0
+ 然后requestor节点的LMD0会通知申请资源的前台进程

也就是说LMD主要处理global enqueue 的请求, 而LCK0主要处理本实例的lock.
另外,RAC上的global deadlock 也是由LMD来发现的。

LCK0: Instance Enqueue Process。LCK0进程主要处理非cache fustion的资源请求,比如library 和row cache 请求。
LCK0处理在实例一级的锁:
 Row cache entries
 Library cache entries
 Result cache entries
这些实例级的锁的owner, waiter是LCK0进程。
只要这个实例的锁的owner是LCK0,那么这个实例的任何一个连接都可以使用这种cached的metedata.
如果本地的实例没有拥有这个lock,那么需要申请这个lock,前台进程会等待DFS Lock Handle。

另外,当shared pool出现压力需要释放一些内存来存放新的cursor时,LCK进程会将dictionary cache 的一些内存进行释放。

LMON: Global Enqueue Service Monitor。LMON用于监控整个集群的global enqueues和resources, 而且会执行global enqueue recovery。实例异常终止后,会由LMON来进行GCS内存方面的处理。当一个实例加入或者离开集群后,LMON会对lock和resource进行reconfiguration.另外LMON会在不同的实例间进行通讯检查,如果发现对方通讯超时,就会发出节点eviction,所以很多时候节点发生eviction后(ORA-481, ORA-29740等),我们需要查看LMON的trace来了解eviction的原因。

还有,在DRM(Dynamic Resource management)中,LMD会监控需要进行remaster的queue,然后把任务发送给LMON进程,LMON进程来实施remaster。

LMS: Global Cache Service Process。 LMS进程会维护在Global Resource Directory (GRD)中的数据文件以及每个cached block的状态。LMS用于在RAC的实例间进行message以及数据块的传输。LMS是Cache Fusion的一个重要部分。LMS进程可以说是RAC上最活跃的后台进程,会消耗较多的CPU.一般每个实例会有多个LMS进程,每个Oracle版本的默认的LMS进程数目会有所不同,大部分版本的默认值是:MIN(CPU_COUNT/2, 2))

DIAG: Diagnostic Capture Process。用来打印诊断信息。diag进程会响应别的进程发出的dump请求,将相关的诊断信息写到diag trace文件中。在RAC上,当发出global oradebug请求时,会由每个实例的diag进程来打印诊断信息到diag trace中。

比如:下面的命令用了“-g”,那么生成的dump信息会分别写到每个实例的diag trace文件中:
SQL>oradebug -g all hanganalyze 3
SQL>oradebug -g all dump systemstate 266

ASMB: ASM Background Process。用于和ASM实例进行通讯,用来管理storage和提供statistics。当使用ASMCMD的cp命令时,需要用到ASM实例上的ASMB进程,数据库实例的spfile如果位于存于ASM上,那么也会用到ASMB进程。如果OCR存放在ASM中,也会用到ASMB。

RBAL:ASM Rebalance Master Process。作为ASM磁盘组进行rebalance时的协调者(Coordinator)。在数据库实例上,由它来管理ASM磁盘组。

Onnn:ASM Connection Pool Process。是从数据库实例连接到ASM实例上的一些连接池,通过这些连接池,数据库可以发送
消息给ASM实例。比如,由它将打开文件的请求发送给ASM实例,这些连接池只处理一些较短的请求,不处理创建文件这种较长的请求。

PZ:PQ slaves。PZnn进程(从99开始)用于查询GV$视图,这种查询需要在每个实例上并行执行。如果需要更多的PZ进程,会自动生成PZ98, PZ97,...(降序)。

11G 特有的:
PING:Interconnect Latency Measurement Process。用来检查集群中各个实例间的私网通讯状况。每个实例每隔几秒会发送给其它实例一些消息,这些消息会由其它实例的PING进程收到。发送和接收信息花费的时间会被记录下来并判断是否正常。

LMHB: Global Cache/Enqueue Service Heartbeat Monitor。监控本地的LMON, LMD, LCK0,RMS0 and LMSn等进程是否运行正常,是否被阻塞或者已经hang了。

RMSn:Oracle RAC Management Process。完成对RAC的一些管理任务,比如当一个新的实例加入到集群后,给这个实例创建相关的资源。

RSMN: Remote Slave Monitor Process。管理后台的slave进程的创建,作为远程实例的协调者来完成一些任务。

GTXn: Global Transaction Process。在RAC环境中对于XA 事务提供透明支持,维护在RAC中的XA事务的global信息,完成global事务的两阶段提交。

RCBG: Result Cache Background Process。这个进程用来处理RAC上Result Cache相关的消息。

ACMS: Atomic Control File to Memory Service Process。作为每个实例上的agent来保证SGA的更新在RAC的所有实例上都是同步的,或者是全局成功提交,或者由于一些问题而导致全局回滚。

请参考官方文档:
http://docs.oracle.com/cd/E11882_01/server.112/e25513/bgprocesses.htm#REFRN104
Oracle® Database Reference
11g Release 2 (11.2)
Part Number E25513-03
F Background Processes

My Oracle Support文档:
New Background Processes In 11g (Doc ID 444149.1)

Oracle CRS/GI 进程介绍

     在10g和11.1,Oracle的集群称为CRS(Oracle Cluster Ready Service), 在11.2,Oracle的集群称为GI(Grid Infrastructure)。 对于CRS/GI,他们的一些核心进程的功能基本类似,但是在11.2,新增了很多新的Deamon进程。

10.2 CRS:
$ ps -ef|grep crs/bin
root      4373  3605  0 Feb25 ?        00:02:49 /u01/app/crs/bin/crsd.bin reboot
oracle    4380  4379  0 Feb25 ?        00:00:03 /u01/app/crs/bin/evmd.bin
oracle    4925  4888  0 Feb25 ?        00:00:00 /u01/app/crs/bin/oclsomon.bin
root      4928  4483  0 Feb25 ?        00:00:00 /u01/app/crs/bin/oprocd.bin run -t 1000 -m 10000 -
hsi 5:10:50:75:90 -f
oracle    5065  4512  0 Feb25 ?        00:00:54 /u01/app/crs/bin/ocssd.bin
oracle    6825  4380  0 Feb25 ?        00:00:00 /u01/app/crs/bin/evmlogger.bin -o

11.2 GI:
$ ps -ef|grep grid/bin
root      6656     1  0 Feb25 ?        00:09:20 /u01/app/11.2.0/grid/bin/ohasd.bin reboot
grid      7960     1  0 Feb25 ?        00:16:54 /u01/app/11.2.0/grid/bin/oraagent.bin
grid      7972     1  0 Feb25 ?        00:00:05 /u01/app/11.2.0/grid/bin/mdnsd.bin
grid      7982     1  0 Feb25 ?        00:03:45 /u01/app/11.2.0/grid/bin/gpnpd.bin
grid      7993     1  0 Feb25 ?        00:14:19 /u01/app/11.2.0/grid/bin/gipcd.bin
root      7995     1  1 Feb25 ?        00:41:42 /u01/app/11.2.0/grid/bin/orarootagent.bin
root      8010     1  0 Feb25 ?        00:28:03 /u01/app/11.2.0/grid/bin/osysmond.bin
root      8026     1  0 Feb25 ?        00:01:31 /u01/app/11.2.0/grid/bin/cssdmonitor
root      8040     1  0 Feb25 ?        00:02:22 /u01/app/11.2.0/grid/bin/cssdagent
grid      8057     1  1 Feb25 ?        00:48:04 /u01/app/11.2.0/grid/bin/ocssd.bin
root      8136     1  0 Feb25 ?        00:02:49 /u01/app/11.2.0/grid/bin/octssd.bin reboot
grid      8158     1  0 Feb25 ?        00:02:24 /u01/app/11.2.0/grid/bin/evmd.bin
root      8278     1  0 Feb25 ?        00:04:18 /u01/app/11.2.0/grid/bin/crsd.bin reboot
grid      8357  8158  0 Feb25 ?        00:00:00 /u01/app/11.2.0/grid/bin/evmlogger.bin -o
/u01/app/11.2.0/grid/evm/log/evmlogger.info -l /u01/app/11.2.0/grid/evm/log/evmlogger.log
grid      8406     1  0 Feb25 ?        00:11:22 /u01/app/11.2.0/grid/bin/oraagent.bin
root      8414     1  1 Feb25 ?        00:36:22 /u01/app/11.2.0/grid/bin/orarootagent.bin

我们对这些常见的集群进程做一些解释:

各个版本共有的:
1. ocssd.bin:这是一个很核心的进程,如果它异常终止会导致这个节点的集群或者主机重启。这个进程主要用于检查表决盘能否正常访问,节点私网间的通信是否正常。数据库实例上的LMON进程也会注册到CSSD上,这样CSSD会通过LMON来了解数据库实例的健康情况。
  如果节点发生了主机自动重启,需要查看ocssd的日志,位于: <CRS_HOME>/log/<host>/cssd。

  可以参考下面的文档来了解节点重启:
如何诊断节点重启问题
11gR2 如何诊断节点重启问题

2. crsd.bin: 这个进程主要用于管理集群中的资源。用来启动、停止检查一些资源,比如数据库实例、ASM、监听、磁盘组、VIP等。在11.2,这些具体的操作由对应的agent执行。另外,OCR的维护也是由CRSD完成的。
   当发现某些资源异常终止后,首先需要查看crsd的日志:<CRS_HOME>/log/<host>/crsd。

3. evmd.bin: 事件监控(event monitor)进程,由它来发布集群事件,比如实例启动、停止等事件。

4. ons进程:Oracle Notification Service daemon,它用于接收evmd发来的集群事件,然后将这些事件发送给应用预订者或者本地的监听,这样就可以实现FAN(Fast Application Notification),应用能够接收到这些事件并进行处理。

5. gsd: 只有当CRS或者GI上需要管理9i的数据库时才需要。在11.2, gsd 默认就是offline的。
可以参考My Oracle Support 文档: GSD Is Used Only if 9i RAC Database is Present (Doc ID 429966.1)

10g和 11.1特有的:
1. oprocd.bin:Oracle Clusterware Process Monitor Daemon,用来监控主机hang,如果发现主机hang后会发起主机重启。只有未使用第三方的集群软件时才运行,Linux上从10.2.0.4开始使用。
   oprocd的日志会在:/etc/oracle/oprocd/*.log.* 或者 /var/opt/oracle/oprocd/*.log.*。

2. oclsomon.bin: 用来监控ocssd进程是否hang,如果发现hang,会发起reboot.


11.2特有的:
1. cssdagent(11.2): 这个进程由ohasd启动,然后由它来启动、停止、检查ocssd进程,以root身份运行。
   它的日志位于:<GRID_HOME>/log/<host>/agent/ohasd/oracssdagent_root

2. cssdmonitor(11.2):监控cssdagent,并且检查节点hang(类似于oprocd),监控ocssd进程是否hang(类似于oclsomon),监控vendor clusterware(类似于vmon),以root身份运行。
   它的日志位于:<GRID_HOME>/log/<host>/agent/ohasd/oracssdmonitor_root

3. ohasd.bin: 在GI启动时,最先启动的就是ohasd,然后由它启动agent(orarootagent,oraagent, cssdagnet 和 cssdmonitor) ,各个agent再启动对应的进程。 
    如果GI启动过程有问题,可以查看一下ohasd的日志:<GRID_HOME>/log/<host>/agent/ohasd


4. mdnsd.bin:这个进程通过多播(Multicast)发现集群中的节点和所有的网卡信息。一定要确定集群中的网卡支持多播,而且节点间的通信正常。
   它的日志位于:<GRID_HOME>/log/<host>/mdnsd

5. gpnpd.bin: 发布构建集群所需要的bootstrap 信息,并且在集群的所有节点之间同步gpnp profile。
   它的日志位于:<GRID_HOME>/log/<host>/gpnpd

6. gipcd.bin: 这个进程负责管理集群中所有的私网(cluster interconnect)网卡。私网信息是通过gpnpd获得的。
   它的日志位于:<GRID_HOME>/log/<host>/gipcd

7. gnsd(可选): Grid Naming Service. 相当于子DNS,功能和DNS类似,会取代使用/etc/hosts进行主机的解析。
   它的日志位于:<GRID_HOME>/log/<host>/gnsd

8. octssd.bin: The Cluster Time Sync Service(CTSS) 用于各个节点间的时钟同步,集群中的一个节点的时钟会作为参照节点,其它节点和这个节点进行时钟同步。注意:当第三方时间同步软件(例如:NTP) 存在时,CTSS会以‘观察者’的方式运行,并不修改节点时间,但是,如果CTSS没有发现第三方时间同步软件,它会开始修改节点时间以便和参考节点同步。
   它的日志位于:<GRID_HOME>/log/<host>/ctssd.

9. osysmond.bin :这是Oracle Cluster Health Monitor(CHM)的主要进程,这个进程在所有节点都会运行,sysmond会将每个节点的资源使用情况发送给cluster logger service,后者将会把所有节点的信息都接收并保存到CHM的资料库。
   它的日志位于:<GRID_HOME>/log/<host>/crfmond/crfmond.log

10. ologgerd: 这是Oracle Cluster Health Monitor(CHM)的另一个主要进程,在一个集群中的,ologgerd 会有一个主机点(master),还有一个备节点(standby)。当ologgerd在当前的节点遇到问题无法启动后,它会在备用节点启用。
   它的日志位于:<GRID_HOME>/log/<host>/crflogd/crflogd.log

关于CHM,请参考:
11gR2 新特性:Oracle Cluster Health Monitor(CHM)简介

11. <XXX>agent.bin:在11.2,各个资源的启动、停止和检查都是由agent来执行的。ohasd 会把这些agent启动。

Agent包括两种,一种是ohasd的:
oraagent_grid: 启动/停止/检查/清除ora.asm, ora.evmd, ora.gipcd, ora.gpnpd, ora.mdnsd等资源。
orarootagent_root:启动/停止 /检查/清除 ora.crsd, ora.ctssd, ora.diskmon, ora.drivers.acfs, ora.crf (11.2.0.2)等资源。
oracssdagent_root: 启动/停止/检查 ocssd进程。
oracssdmonitor_root:监控cssdagent进程。

它们的日志位于:<GRID_HOME>/log/<host>/agent/ohasd

另一种是crsd的:
oraagent_grid: 启动/停止/检查/清除 asm, ora.eons, ora.LISTENER.lsnr, SCAN listeners, ora.ons, diskgroup  等资源
oraagent_oracle: 启动/停止/检查/清除 service, database 等资源
orarootagent_root : 启动/停止/检查/清除 GNS, VIP, SCAN VIP and network 等资源.
scriptagent_grid:  应用服务定制的服务。

它们的日志位于:<GRID_HOME>/log/<host>/agent/crsd

关于agent的更多信息,请参考文章 "11gR2 Agent 简介"。

星期二 一月 22, 2013

11gR2 新特性: Rebootless Restart


众所周知,当集群出现问题时,例如某个节点丢失网络心跳,或者不能够访问表决盘,或者节点出现了严重的性能问题等,CRS会选择将某个节点的OS 重启,以便保证集群的一致性。当然,大部分的重启都是由CRS的核心进程ocssd.bin发起的。 但是,如果CRS 只是节点上的应用之一或者私网和存储的问题只是短时间的出现,那么重启节点的行为就会导致节点上所有的应用全部停止,这在很多系统上并不是我们希望看到的。

所以从版本11.2.0.2 开始,oracle新特性rebootless restart被介绍。当出现以下情况的时候,集群件(GI)会重新启动集群管理软件,而不是将节点重启。
1.当某个节点连续丢失网络心跳超过misscount时。
2.当某个节点不能访问大多数表决盘(VF)时。
3.当member kill 被升级成为node kill的时候。
在之前的版本,以上情况,集群管理软件(CRS)会直接重启节点。

之后,我们通过几个例子了解上面提到的几种情况。
1.当某个节点连续丢失网络心跳超过misscount的情况
2010-08-13 17:00:26.213: [    CSSD][4073040800]clssnmPollingThread: node <nodename> (1) at 50% heartbeat fatal, removal in 14.540 seconds
……
2010-08-13 17:00:33.227: [    CSSD][4073040800]clssnmPollingThread: node <nodename> (1) at 75% heartbeat fatal, removal in 7.470 seconds
……
2010-08-13 17:00:38.236: [    CSSD][4073040800]clssnmPollingThread: node <nodename> (1) at 90% heartbeat fatal, removal in 2.460 seconds, seedhbimpd 1 ?本地节点report 远程节点丢失本地心跳
……
2010-08-13 17:00:40.707: [    CSSD][4052061088](:CSSNM00008: )clssnmCheckDskInfo: Aborting local node to avoid splitbrain. Cohort of 1 nodes with leader 2, <nodename>, is smaller than cohort of 1 nodes led by node 1, <nodename>, based on map type 2 ? 为了避免split-brain ,本地节点重新启动GI。
2010-08-13 17:00:40.707: [    CSSD][4052061088]###################################
2010-08-13 17:00:40.707: [    CSSD][4052061088]clssscExit: CSSD aborting from thread clssnmRcfgMgrThread
2010-08-13 17:00:40.707: [    CSSD][4052061088]###################################
2.当某个节点不能访问大多数表决盘(VF)的情况
2010-08-13 18:31:23.782: [    CSSD][150477728]clssnmvDiskOpen: Opening /dev/sdb8
2010-08-13 18:31:23.782: [   SKGFD][150477728]Handle 0xf43fc6c8 from lib :UFS:: for disk :/dev/sdb8:

2010-08-13 18:31:23.782: [    CLSF][150477728]Opened hdl:0xf4365708 for dev:/dev/sdb8:
2010-08-13 18:31:23.787: [   SKGFD][150477728]ERROR: -9(Error 27072, OS Error (Linux Error: 5: Input/output error ? 访问表决盘出错。
Additional information: 4
Additional information: 720913
Additional information: -1)
)
2010-08-13 18:31:23.787: [    CSSD][150477728](:CSSNM00060: )clssnmvReadBlocks: read failed at offset 17 of /dev/sdb8
……
2010-08-13 18:34:38.206: [    CSSD][4110736288](:CSSNM00018: )clssnmvDiskCheck: Aborting, 0 of 1 configured voting disks available, need 1 ?在经过long disk timeout时间之后,GI被重新启动。
2010-08-13 18:34:38.206: [    CSSD][4110736288]###################################
2010-08-13 18:34:38.206: [    CSSD][4110736288]clssscExit: CSSD aborting from thread clssnmvDiskPingMonitorThread
2010-08-13 18:34:38.206: [    CSSD][4110736288]###################################

3.member kill 被升级成为node kill的情况。
2013-01-14 23:49:52.093: [    CSSD][45]clssgmmkLocalKillThread: Time up. Timeout 30500 Start time 130388522 End time 130419022 Current time 130419087 ?member kill 超时发生
2013-01-14 23:49:52.093: [    CSSD][45]clssgmmkLocalKillResults: Replying to kill request from remote node 1 kill id 1 Success map 0x00000000 Fail map 0x00000000
……
2013-01-14 23:49:52.235: [    CSSD][31](:CSSNM00005: )clssnmvDiskKillCheck: Aborting, evicted by node <nodename>, number 1, sync 239654498, stamp 130416886 ?该节点被驱逐出集群,也就是重启GI
2013-01-14 23:49:52.235: [    CSSD][31]###################################
2013-01-14 23:49:52.235: [    CSSD][31]clssscExit: CSSD aborting from thread clssnmvKillBlockThread
2013-01-14 23:49:52.235: [    CSSD][31]###################################
2013-01-14 23:49:52.235: [    CSSD][31](:CSSSC00012: )clssscExit: A fatal error occurred and the CSS daemon is terminating abnormally

从上面的输出,我们能看到三种情况中ocssd.bin进程都能够正常地工作,当出现问题时,能过做出正确的决定。所以,rebootless restart能够保证由ocssd.bin主动发起的重启。但是,如果是由于ocssd.bin 出现问题(例如:挂起),或者操作系统性能引起的重启,rebootless restart是无法起作用的,因为,对于这种情况ocssd.bin已经不能正常工作,节点重启仍然不可避免。具体关于如何诊断节点重启的问题,请参考之前的文章 “11gR2 如何诊断节点重启问题”。

GI 在重启集群之前,首先要对集群进行graceful shutdown, 基本的步骤如下。
1.停止本地节点的所有心跳(网络心跳,磁盘心跳和本地心跳)。
2.通知cssd agent,ocssd.bin即将停止
3.停止所有注册到css的具有i/o能力的进程,例如 lmon。
4.cssd通知crsd 停止所有资源,如果crsd不能成功的停止所有的资源,节点重启仍然会发生。
5.Cssd等待所有的具有i/o能力的进程退出,如果这些进程在short i/o timeout时间内不能不能全部推迟,节点重启仍然会发生。
6.通知cssd agent 所有的有i/o能力的进程全部退出。
7.Ohasd 重新启动集群。
8.本地节点通知其他节点进行集群重配置。

综上所述,对于11.2.0.2 及以上版本的集群,如果您发现了节点重启,那么,ocssd.bin 挂���或者操作系统性能的问题应该是首先检查的内容。当然,如果rebootless restart的gracefull shutdown 不能在指定的时间内完成,节点重启仍然会发生,这需要查看ocssd.log进行诊断。


如果您希望对这篇文章进行进一步的讨论,请在以下的链接回复。


https://communities.oracle.com/portal/server.pt/community/view_discussion_topic/216?threadid=536867&Portlet=Create%20Discussion&PrevPage=Communities-CreateDiscussion

星期五 六月 15, 2012

11gR2 新特性:Oracle Cluster Health Monitor(CHM)简介

   Cluster Health Monitor(以下简称CHM)是一个Oracle提供的工具,用来自动收集操作系统的资源(CPU、内存、SWAP、进程、I/O以及网络等)的使用情况。相对于OSWatcher,CHM直接调用OS的API来降低开销,而OSWatcher则是直接调用UNIX命令。另外,CHM的实时性更强,每秒收集一次数据(在11.2.0.3,改为了5秒一次)。 OSWatcher 的优点是可以用traceroute命令检测私网间的连通性,而且生成的数据的保留时间可以设置得很长。如果可以的话,最好是两个工具都使用。

   这些系统资源数据对于诊断集群系统的节点重启、Hang、实例驱逐(Eviction)、性能问题等是非常有帮助的。另外,用户可以使用CHM来及早发现一些系统负载高、内存异常等问题,从而避免产生更严重的问题。

CHM会自动安装在下面的软件:
    11.2.0.2 及更高版本的 Oracle Grid Infrastructure for Linux (不包括Linux Itanium) 、Solaris (Sparc 64 和 x86-64)
    11.2.0.3 及更高版本 Oracle Grid Infrastructure for AIX 、 Windows (不包括Windows Itanium)。

    在11.2.0.2之前的集群(10.2到11.2.0.1),可以安装独立版的CHM。目前支持的平台有Linux x86 和Linux x86-64,还有32位的Windows Server 2003 SP 2。独立版的CHM并不一定要安装在集群环境,单机环境也可以使用。关于如何安装独立版的CHM,请参考另一篇博客:
如何安装独立版的CHM(Oracle Cluster Health Monitor)


    在集群中,可以通过下面的命令查看CHM对应的资源(ora.crf)的状态:
    $ crsctl stat res -t -init
    --------------------------------------------------------------------------------
    NAME           TARGET  STATE        SERVER                   STATE_DETAILS       Cluster Resources
ora.crf        ONLINE  ONLINE       rac1

CHM主要包括两个服务:
    1). System Monitor Service(osysmond):这个服务在所有节点都会运行,osysmond会将每个节点的资源使用情况发送给cluster logger service,后者将会把所有节点的信息都接收并保存到CHM的资料库。
      $ ps -ef|grep osysmond
       root      7984     1  0 Jun05 ?        01:16:14 /u01/app/11.2.0/grid/bin/osysmond.bin

    2). Cluster Logger Service(ologgerd):在一个集群中的,ologgerd 会有一个主机点(master),还有一个备节点(standby)。当ologgerd在当前的节点遇到问题无法启动后,它会在备用节点启用。

     主节点:
     $ ps -ef|grep ologgerd
       root      8257     1  0 Jun05 ?        00:38:26 /u01/app/11.2.0/grid/bin/ologgerd -M -d       /u01/app/11.2.0/grid/crf/db/rac2

     备节点:
      $ ps -ef|grep ologgerd
       root      8353     1  0 Jun05 ?        00:18:47 /u01/app/11.2.0/grid/bin/ologgerd -m rac2 -r -d
/u01/app/11.2.0/grid/crf/db/rac1


CHM诊断日志:如果CHM的运行异常,可以查看下面的日志:
$GRID_HOME/log/<nodename>/crflogd/crflogd.log
$GRID_HOME/log/<nodename>/crfmond/crfmond.log

GI 中的服务ora.crf 是CHM对应的资源,可以使用下面的命令来启停CHM(不推荐停止该服务):
用root用户:
$GRID_HOME/bin/crsctl stop res ora.crf -init
$GRID_HOME/bin/crsctl start res ora.crf -init

CHM Repository:用于存放收集到数据,默认情况下,会存在于Grid Infrastructure home 下 ,需要1 GB 的磁盘空间,每个节点大约每天会占用0.5GB的空间,您可以使用OCLUMON来调整它的存放路径以及允许的空间大小(最多只能保存3天的数据)。

下面的命令用来查看它当前设置:
     $ oclumon manage -get reppath
       CHM Repository Path = /u01/app/11.2.0/grid/crf/db/rac2
       Done

     $ oclumon manage -get repsize
       CHM Repository Size = 68082 <====单位为秒
       Done

     修改路径:
     $ oclumon manage -repos reploc /shared/oracle/chm

     修改大小:
     $ oclumon manage -repos resize 68083 <==在3600(小时) 到 259200(3天)
之间
      rac1 --> retention check successful
      New retention is 68083 and will use 1073750609 bytes of disk space
      CRS-9115-Cluster Health Monitor repository size change completed on all nodes.
      Done

获得CHM生成的数据的方法有两种:
     1. 一种是使用Grid_home/bin/diagcollection.pl:
        1). 首先,确定cluster logger service的主节点:
         $ oclumon manage -get master
         Master = rac2


        2).用root身份在主节点rac2执行下面的命令:
         # <Grid_home>/bin/diagcollection.pl -collect -chmos -incidenttime inc_time -incidentduration duration
         inc_time是指从什么时间开始获得数据,格式为MM/DD/YYYY24HH:MM:SS, duration指的是获得开始时间后多长时间的数据。

         比如:# diagcollection.pl -collect -crshome /u01/app/11.2.0/grid -chmoshome  /u01/app/11.2.0/grid -chmos -incidenttime 06/15/201215:30:00 -incidentduration 00:05

       3).运行这个命令之后,CHM的数据会生成在文件chmosData_rac2_20120615_1537.tar.gz。

    2. 另外一种获得CHM生成的数据的方法为oclumon:
        $oclumon dumpnodeview [[-allnodes] | [-n node1 node2] [-last "duration"] | [-s "time_stamp" -e "time_stamp"] [-v] [-warning]] [-h]

        -s表示开始时间,-e表示结束时间
       $ oclumon dumpnodeview -allnodes -v -s "2012-06-15 07:40:00" -e "2012-06-15 07:57:00" > /tmp/chm1.txt

       $ oclumon dumpnodeview -n node1 node2 node3 -last "12:00:00" >/tmp/chm1.txt
       $ oclumon dumpnodeview -allnodes -last "00:15:00" >/tmp/chm1.txt


下面是/tmp/chm1.txt中的部分内容:
----------------------------------------
Node: rac1 Clock: '06-15-12 07.40.01' SerialNo:168880
----------------------------------------

SYSTEM:
#cpus: 1 cpu: 17.96 cpuq: 5 physmemfree: 32240 physmemtotal: 2065856 mcache: 1064024 swapfree: 3988376 swaptotal: 4192956 ior: 57 io
w: 59 ios: 10 swpin: 0 swpout: 0 pgin: 57 pgout: 59 netr: 65.767 netw: 34.871 procs: 183 rtprocs: 10 #fds: 4902 #sysfdlimit: 6815744
 #disks: 4 #nics: 3  nicErrors: 0

TOP CONSUMERS:
topcpu: 'mrtg(32385) 64.70' topprivmem: 'ologgerd(8353) 84068' topshm: 'oracle(8760) 329452' topfd: 'ohasd.bin(6627) 720' topthread:
 'crsd.bin(8235) 44'

PROCESSES:

name: 'mrtg' pid: 32385 #procfdlimit: 65536 cpuusage: 64.70 privmem: 1160 shm: 1584 #fd: 5 #threads: 1 priority: 20 nice: 0
name: 'oracle' pid: 32381 #procfdlimit: 65536 cpuusage: 0.29 privmem: 1456 shm: 12444 #fd: 32 #threads: 1 priority: 15 nice: 0
...
name: 'oracle' pid: 8756 #procfdlimit: 65536 cpuusage: 0.0 privmem: 2892 shm: 24356 #fd: 47 #threads: 1 priority: 16 nice: 0

----------------------------------------
Node: rac2 Clock: '06-15-12 07.40.02' SerialNo:168878
----------------------------------------

SYSTEM:
#cpus: 1 cpu: 40.72 cpuq: 8 physmemfree: 34072 physmemtotal: 2065856 mcache: 1005636 swapfree: 3991808 swaptotal: 4192956 ior: 54 io
w: 104 ios: 11 swpin: 0 swpout: 0 pgin: 54 pgout: 104 netr: 77.817 netw: 33.008 procs: 178 rtprocs: 10 #fds: 4948 #sysfdlimit: 68157
44 #disks: 4 #nics: 4  nicErrors: 0

TOP CONSUMERS:
topcpu: 'orarootagent.bi(8490) 1.59' topprivmem: 'ologgerd(8257) 83108' topshm: 'oracle(8873) 324868' topfd: 'ohasd.bin(6744) 720' t
opthread: 'crsd.bin(8362) 47'

PROCESSES:

name: 'oracle' pid: 9040 #procfdlimit: 65536 cpuusage: 0.19 privmem: 6040 shm: 121712 #fd: 33 #threads: 1 priority: 16 nice: 0
...


  关于CHM的更多解释,请参考Oracle官方文档:
  http://docs.oracle.com/cd/E11882_01/rac.112/e16794/troubleshoot.htm#CWADD92242
  Oracle® Clusterware Administration and Deployment Guide
  11g Release 2 (11.2)
  Part Number E16794-17

  或者 My Oracle Support文档:
  Cluster Health Monitor (CHM) FAQ (Doc ID 1328466.1)

11gR2 Agent 简介

目的:本文会对oracle 11gR2 集群件(Grid Infrastructure,以下简称GI) 新特性 agent进行介绍,包括 agent的功能,常见的agent介绍,以及基本的诊断方法。

适用范围:11.2.0.1及以上版本。

    首先我们对10gR2 crs 管理资源的方法进行简单的介绍。在10gR2 当中,crsd 负责对集群中的资源进行管理。具体说来,crsd 调用相关的racg脚本,产生racg进程对资源进行管理,例如racgvip 脚本用来管理vip资源。这种管理办法,由于是racg进程进行对资源的操作,有时候会存在一些问题。从11gR2 GI开始, agent 作为一个全新的架构对GI中所有的资源进行管理,这种全新的agent 架构使资源管理更加强壮,性能更好。

    接下来我们对agent的特点进行一些介绍。
1.几乎所有的资源和daemon都是由agent 管理的。例如gipc, gpnp等 由ohasd 产生的orarootagent管理。
2.Agent守护进程是多线程的,而且是HA(High Available)进程.
3.Ohasd 会产生下面的agent
        cssdagent(这个agent代表命令“crsctl stat res –t –init” 中的资源ora.cssd )
        orarootagent
        oraagent
        cssdmonitor
    Crsd 会产生下面的agent
        orarootagent
        Oraagent
        用户自定义的agent.
注意:用户oracle和grid都会产生各自对应的oraagent来管理各自的资源。例如 oraagent_grid管理资源ora.asm, oraagent_oracle管理ora.<database_name>.db资源。

    下面我们对agent如何管理资源进行介绍。首先,agent 拥有一些EP(Entry Point),类似于可以对资源执行的动作。
       Start:启动资源
       Stop:停止资源
       Check:检查资源的状态,如果发现了资源状态改变,则agent会通知GI,资源状态发生了改变。
       Clean:清理资源,一般来说清理资源会在资源存在问题,需要重新启动或failover之前发生。
       Abort:中止资源。

    当以上的任意EP结束之后,会返回以下返回值中的一个,而这些返回值也对应着资源的状态。
       ONLINE:在线。对应资源的online状态
       OFFLINE:离线。对应资源的offline状态。对于offline状态,可以细分为planed offline 和unplaned offline。Planed offline是指GI倾向于这个资源处在offline状态,例如我们使用GI相关的工具(srvctl, crsctl)停止了一个资源,这种情况,GI就认为资源应该处于offline状态,因为停止资源的操作是通过GI来实现的。同时,对于planed offline的资源,它的target状态也会被修改为offline状态,这意味着,如果在资源的target状态为offline时重启GI stacks,除非资源的auto_start属性设置为always,否则,该资源不会被自动启动(关于target状态,和属性auto_start的更多信息,请参考oracle联机文档Oracle Clusterware Administration and Deployment Guide 11g Release 2)。对于unplaned offline,是指资源被GI以外的工具停止,例如使用sqlplus手动关闭数据库,在这种情况下,GI并不认为该资源应该处于offline状态,资源的target状态仍然为online,所以,资源在重新启动GI时仍然会被启动,当然除非资源的auto_start属性设置为never。
       UNKNOWN:未知,对应资源的unknown状态。在这种状态下,agent会继续对该资源进行check。
       PARTIAL:资源部分在线,对应资源的intermediate状态。 在这种情况下agent会继续对该资源进行check,并及时更新资源状态。
       FAILED:失败。该返回值说明资源存在问题,不能正常工作,agent会首先执行clean EP,之后根据资源的相关属性进行failover或restart操作。

    之后,我们可以通过下面这张表格了解agent与负责管理的资源的对应关系。




    最后,我们对agent相关的trace文件进行简单的介绍。首先,agent的trace 文件位于路径GRID_HOME/log/<host>/agent下,以下是比较详细的信息。

            GRID_HOME/log/<host>/agent /ohasd/orarootagent_root  <– ohasd产生的orarootagent日志

            GRID_HOME/log/<host>/agent/ohasd/oraagent_grid  <– ohasd产生的oraagent日志

            GRID_HOME/log/<host>/agent/ohasd/oracssdagent_root  <– ohasd产生的cssdagent日志

            GRID_HOME/log/<host>/agent/ohasd/oracssdmonitor_root  <– ohasd产生的cssdmonitor日志

            GRID_HOME/log/<host>/agent/crsd/oraagent_grid  <– crsd产生的oraagent日志,owner为grid

            GRID_HOME/log/<host>/agent/crsd/oraagent_oracle  <– crsd产生的oraagent日志,owner为oracle

            GRID_HOME/log/<host>/agent/crsd/orarootagent_root  <–crsd产生的orarootagent日志

    另外,以下的文件对诊断agent相关的问题也很有帮助。

            集群alert log(Grid_home/log/<hostname>/alert<hostname>.log)

            Grid_home/log/<hostname>/ohasd/ohasd.log

            Grid_home/log/<hostname>/crsd/crsd.log


    由于每个agent需要管理多个资源,所以,如果只是某一个资源存在问题,可以使用有问题的资源名称过滤agent日志会更有效率,当然Agent日志的可读性很好,在这里不进行详细的介绍。Agent如果crash,一般情况下,会产程一个core文件(Grid_home/log/<hostname>/agent/{ohasd|crsd}/<agent名>_<用户名>)和对应的堆栈文件(Grid_home/log/<hostname>/agent/{ohasd|crsd}/<agent名>_<用户名>/<agent名>_<用户名>OUT.log)。


星期四 五月 03, 2012

11g 新特性—— Active Database Duplication for A standby database

简介
------------
从11G开始oracle提供了一个新功能Active Database Duplication for A standby database来创建配置物理standby 数据库。
Active Database Duplication for A standby database这个功能主要从一个正在运行的数据库复制数据文件,控制文件等到一个物理备库(physical standby database)。
这个功能简化了创建standby database过程中在主库备份和备库恢复的环节,实现了自动拷贝主库的控制文件,数据文件等到备库,对比基于备份集的创建standby database过程中需要手动在主库备份,然后将备份集拷贝到备库再手动恢复来说,减少了dba的大量工作。

创建物理standby database过程中的其他环节,如打开主库的force logging,主库init参数的修改等,以及备库开始应用redo log这些环节还需手动来完成的,与以往的创建配置物理standby database 是相同的。

备库的init参数需要在duplicate命令中指定,没有特殊指定的,就会默认使用主库的init参数值。

下面以一个测试例子来具体说明
-----------------------------------
主库:11.2.0.1 单机数据库,db_unique_name=orcl,数据文件存放在文件系统
备库:11.2.0.1 单机数据库,db_unique_name=orabak,使用ASM存储
Data Guard保护模式(Protection mode)采用最大性能模式(MAXIMIZE PERFORMANCE)
redo log传输采用LGWR进程的异步传输方式

1. 打开主库force logging:
SQL>  ALTER DATABASE FORCE LOGGING;

查看主库当前是否为force logging:
SQL> select force_logging from v$database;
FOR
---
YES

2. 修改主库的初始化参数如下:
LOG_ARCHIVE_CONFIG='DG_CONFIG=(orcl,orabak)'
LOG_ARCHIVE_DEST_1=
  'LOCATION=/home/oracle/app/archdir
  VALID_FOR=(ONLINE_LOGFILE,PRIMARY_ROLE)
  DB_UNIQUE_NAME=orcl'
LOG_ARCHIVE_DEST_2=
  'SERVICE=orabak LGWR ASYNC
   VALID_FOR=(ONLINE_LOGFILES,PRIMARY_ROLE)   
   DB_UNIQUE_NAME=orabak'
LOG_ARCHIVE_DEST_STATE_1=ENABLE
LOG_ARCHIVE_DEST_STATE_2=ENABLE
REMOTE_LOGIN_PASSWORDFILE=EXCLUSIVE
LOG_ARCHIVE_MAX_PROCESSES=10

3. 在备库创建ASM 磁盘组 '+DATA',用来存放备库的数据文件,控制文件,standby redo文件等。

4. 在备库创建 adump 路径,与参数audit_file_dest的路径一致
$ mkdir -p /u01/app/admin/orabak/adump

5. 在备库创建init参数文件$ORACLE_HOME/dbs/initorabak.ora',
有了这个临时的init参数文件,我们就可以在duplicate命令运行前将备库的AUXILIARY实例启动到nomount状态,这也是运行duplicate命令的一个必要条件。

initorabak.ora文件只有一行信息:
DB_NAME=orcl

6. 将密码文件从主库服务器拷贝到备库服务器,并且重命名:
$ mv orapworcl orapworabak

7. 在主库服务器和备库服务器, 编辑添加下面信息到$ORACLE_HOME/network/tnsnames.ora
orabak =
 (DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.113)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SERVICE_NAME = orabak)
   ))

orcl =
 (DESCRIPTION =
   (ADDRESS_LIST =
     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.112)(PORT = 1521))
   )
   (CONNECT_DATA =
     (SERVICE_NAME = orcl)
   ))

8. 在备库服务器, 添加静态注册信息到 $GRID_HOME/network/listener.ora文件,
这主要是由于AUXILIARY实例启动到nomount状态时,listener无法注册AUXILIARY实例,listener会标志Auxiliary实例为'blocked'状态,因此duplicate命令就无法通过TNS的方式连接到Auxiliary实例,为了解决这个问题,需要先手动静态注册数据库实例到listener上。
当Data Guard配置完成后,就可以删除静态注册的配置信息。
(本测试使用ASM,因此需要安装GRID,有效的listener.ora文件是在GRID_HOME下面)

LISTENER =
 (DESCRIPTION_LIST =
   (DESCRIPTION =
     (ADDRESS = (PROTOCOL = IPC)(KEY = ANYTHING))
     (ADDRESS = (PROTOCOL = TCP)(HOST = 192.168.1.113)(PORT = 1521))
   ) )

SID_LIST_LISTENER =
 (SID_LIST =
   (SID_DESC =
     (GLOBAL_DBNAME = orabak)
     (ORACLE_HOME = /home/oracle/app/product/11.2)
     (SID_NAME = orabak)
   ) )

9. 在备库服务器,执行duplicate命令前,先启动AUXILIARY实例到 nomount 状态:
$ export ORACLE_SID=orabak
$ sqlplus / as sysdba
SQL> startup nomount;

10. 在备库测试与AUXILIARY实例的连接和与主库的连接,如果连接成功,继续执行下面的步骤,
很多时候duplicate命令失败都是由于连接失败导致的。
$ sqlplus sys/oracle@orabak as sysdba
$ sqlplus sys/oracle@orcl as sysdba


11. 创建备库
在duplicate命令中指定关键字'FOR STANDBY'和'FROM ACTIVE DATABASE'表示从一个active的数据库来复制创建物理备库
参数'DORECOVER'表示duplicate命令会执行recover动作,否则duplicate命令只执行restore,
备库与主库不同的初始化参数,需要在duplicate命令中特殊指定,这样创建备库的spfile时就会用指定的值替换主库的参数值,
主库与备库的数据文件的路径不同,因此设置参数'DB_FILE_NAME_CONVERT'

% rman target sys/oracle@orcl AUXILIARY SYS/oracle@orabak
RMAN>
DUPLICATE TARGET DATABASE
FOR STANDBY
FROM ACTIVE DATABASE
DORECOVER
SPFILE
SET "db_unique_name"="orabak"
SET FAL_SERVER="orcl"
SET LOG_ARCHIVE_DEST_1='LOCATION=/u01/app/archdir_sbredo
                       VALID_FOR=(STANDBY_LOGFILE,STANDBY_ROLE) DB_UNIQUE_NAME=orabak'
SET CONTROL_FILES '+DATA/orabak/control01.ctl'
set diagnostic_dest='/u01/app'
set audit_file_dest='/u01/app/admin/orabak/adump'
set DB_FILE_NAME_CONVERT='/home/oracle/app/oradata/orcl','+DATA/orabak/datafile'
NOFILENAMECHECK;


以下是duplicate standby database过程中屏幕的log信息
-----------------------------------------------------
Starting Duplicate Db at 15-APR-12
using target database control file instead of recovery catalog
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=19 device type=DISK

contents of Memory Script:

{
   backup as copy reuse
   targetfile  '/home/oracle/app/product/11.2/dbs/orapworcl' auxiliary format
 '/u01/app/product/11.2/dbs/orapworabak'   targetfile
 '/home/oracle/app/product/11.2/dbs/spfileorcl.ora' auxiliary format
 '/u01/app/product/11.2/dbs/spfileorabak.ora'   ;
   sql clone "alter system set spfile= ''/u01/app/product/11.2/dbs/spfileorabak.ora''";
}
executing Memory Script

Starting backup at 15-APR-12
allocated channel: ORA_DISK_1
channel ORA_DISK_1: SID=38 device type=DISK
Finished backup at 15-APR-12

sql statement: alter system set spfile= ''/u01/app/product/11.2/dbs/spfileorabak.ora''

contents of Memory Script:
{
   sql clone "alter system set  db_unique_name =
 ''orabak'' comment=
 '''' scope=spfile";
   sql clone "alter system set  FAL_SERVER =
 ''orcl'' comment=
 '''' scope=spfile";
   sql clone "alter system set  LOG_ARCHIVE_DEST_1 =
 ''LOCATION=/u01/app/archdir_sbredo                       VALID_FOR=(STANDBY_LOGFILE,STANDBY_ROLE) DB_UNIQUE_NAME=orabak'' comment=
 '''' scope=spfile";
   sql clone "alter system set  CONTROL_FILES =
 ''+DATA/orabak/control01.ctl'' comment=
 '''' scope=spfile";
   sql clone "alter system set  diagnostic_dest =
 ''/u01/app'' comment=
 '''' scope=spfile";
   sql clone "alter system set  audit_file_dest =
 ''/u01/app/admin/orabak/adump'' comment=
 '''' scope=spfile";
   sql clone "alter system set  db_file_name_convert =
 ''/home/oracle/app/oradata/orcl'', ''+DATA/orabak/datafile'' comment=
 '''' scope=spfile";
   shutdown clone immediate;
   startup clone nomount;
}
executing Memory Script

sql statement: alter system set  db_unique_name =  ''orabak'' comment= '''' scope=spfile

sql statement: alter system set  FAL_SERVER =  ''orcl'' comment= '''' scope=spfile

sql statement: alter system set  LOG_ARCHIVE_DEST_1 =  ''LOCATION=/u01/app/archdir_sbredo                       VALID_FOR=(STANDBY_LOGFILE,STANDBY_ROLE) DB_UNIQUE_NAME=orabak'' comment= '''' scope=spfile

sql statement: alter system set  CONTROL_FILES =  ''+DATA/orabak/control01.ctl'' comment= '''' scope=spfile

sql statement: alter system set  diagnostic_dest =  ''/u01/app'' comment= '''' scope=spfile

sql statement: alter system set  audit_file_dest =  ''/u01/app/admin/orabak/adump'' comment= '''' scope=spfile

sql statement: alter system set  db_file_name_convert =  ''/home/oracle/app/oradata/orcl'', ''+DATA/orabak/datafile'' comment= '''' scope=spfile

Oracle instance shut down

connected to auxiliary database (not started)
Oracle instance started

Total System Global Area     238530560 bytes

Fixed Size                     1335724 bytes
Variable Size                 83889748 bytes
Database Buffers             150994944 bytes
Redo Buffers                   2310144 bytes

contents of Memory Script:
{
   backup as copy current controlfile for standby auxiliary format  '+DATA/orabak/control01.ctl';
}
executing Memory Script

Starting backup at 15-APR-12
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
copying standby control file
output file name=/home/oracle/app/product/11.2/dbs/snapcf_orcl.f tag=TAG20120415T185859 RECID=8 STAMP=780692341
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:10
Finished backup at 15-APR-12

contents of Memory Script:
{
   sql clone 'alter database mount standby database';
}
executing Memory Script

sql statement: alter database mount standby database

contents of Memory Script:
{
   set newname for tempfile  1 to
 "+DATA/orabak/datafile/temp01.dbf";
   switch clone tempfile all;
   set newname for datafile  1 to
 "+DATA/orabak/datafile/system01.dbf";
   set newname for datafile  2 to
 "+DATA/orabak/datafile/sysaux01.dbf";
   set newname for datafile  3 to
 "+DATA/orabak/datafile/undotbs01.dbf";
   set newname for datafile  4 to
 "+DATA/orabak/datafile/users01.dbf";
   backup as copy reuse
   datafile  1 auxiliary format
 "+DATA/orabak/datafile/system01.dbf"   datafile
 2 auxiliary format
 "+DATA/orabak/datafile/sysaux01.dbf"   datafile
 3 auxiliary format
 "+DATA/orabak/datafile/undotbs01.dbf"   datafile
 4 auxiliary format
 "+DATA/orabak/datafile/users01.dbf"   ;
   sql 'alter system archive log current';
}
executing Memory Script

executing command: SET NEWNAME

renamed tempfile 1 to +DATA/orabak/datafile/temp01.dbf in control file

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

executing command: SET NEWNAME

Starting backup at 15-APR-12
using channel ORA_DISK_1
channel ORA_DISK_1: starting datafile copy
input datafile file number=00001 name=/home/oracle/app/oradata/orcl/system01.dbf
output file name=+DATA/orabak/datafile/system01.dbf tag=TAG20120415T185922
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:24
channel ORA_DISK_1: starting datafile copy
input datafile file number=00003 name=/home/oracle/app/oradata/orcl/undotbs01.dbf
output file name=+DATA/orabak/datafile/undotbs01.dbf tag=TAG20120415T185922
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:13
channel ORA_DISK_1: starting datafile copy
input datafile file number=00002 name=/home/oracle/app/oradata/orcl/sysaux01.dbf
output file name=+DATA/orabak/datafile/sysaux01.dbf tag=TAG20120415T185922
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:13
channel ORA_DISK_1: starting datafile copy
input datafile file number=00004 name=/home/oracle/app/oradata/orcl/users01.dbf
output file name=+DATA/orabak/datafile/users01.dbf tag=TAG20120415T185922
channel ORA_DISK_1: datafile copy complete, elapsed time: 00:00:01
Finished backup at 15-APR-12

sql statement: alter system archive log current

contents of Memory Script:
{
   backup as copy reuse
   archivelog like  "/home/oracle/app/archdir/1_46_778869623.dbf" auxiliary format
 "/u01/app/archdir_sbredo/1_46_778869623.dbf"   archivelog like
 "/home/oracle/app/archdir/1_47_778869623.dbf" auxiliary format
 "/u01/app/archdir_sbredo/1_47_778869623.dbf"   ;
   catalog clone archivelog  "/u01/app/archdir_sbredo/1_46_778869623.dbf";
   catalog clone archivelog  "/u01/app/archdir_sbredo/1_47_778869623.dbf";
   switch clone datafile all;
}
executing Memory Script

Starting backup at 15-APR-12
using channel ORA_DISK_1
channel ORA_DISK_1: starting archived log copy
input archived log thread=1 sequence=46 RECID=45 STAMP=780692365
output file name=/u01/app/archdir_sbredo/1_46_778869623.dbf RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:01
channel ORA_DISK_1: starting archived log copy
input archived log thread=1 sequence=47 RECID=46 STAMP=780692416
output file name=/u01/app/archdir_sbredo/1_47_778869623.dbf RECID=0 STAMP=0
channel ORA_DISK_1: archived log copy complete, elapsed time: 00:00:01
Finished backup at 15-APR-12

cataloged archived log
archived log file name=/u01/app/archdir_sbredo/1_46_778869623.dbf RECID=1 STAMP=780696505

cataloged archived log
archived log file name=/u01/app/archdir_sbredo/1_47_778869623.dbf RECID=2 STAMP=780696505

datafile 1 switched to datafile copy
input datafile copy RECID=8 STAMP=780696506 file name=+DATA/orabak/datafile/system01.dbf
datafile 2 switched to datafile copy
input datafile copy RECID=9 STAMP=780696506 file name=+DATA/orabak/datafile/sysaux01.dbf
datafile 3 switched to datafile copy
input datafile copy RECID=10 STAMP=780696506 file name=+DATA/orabak/datafile/undotbs01.dbf
datafile 4 switched to datafile copy
input datafile copy RECID=11 STAMP=780696506 file name=+DATA/orabak/datafile/users01.dbf

contents of Memory Script:
{
   set until scn  303787;
   recover
   standby
   clone database
    delete archivelog
   ;
}
executing Memory Script

executing command: SET until clause

Starting recover at 15-APR-12
allocated channel: ORA_AUX_DISK_1
channel ORA_AUX_DISK_1: SID=25 device type=DISK

starting media recovery

archived log for thread 1 with sequence 46 is already on disk as file /u01/app/archdir_sbredo/1_46_778869623.dbf
archived log for thread 1 with sequence 47 is already on disk as file /u01/app/archdir_sbredo/1_47_778869623.dbf
archived log file name=/u01/app/archdir_sbredo/1_46_778869623.dbf thread=1 sequence=46
archived log file name=/u01/app/archdir_sbredo/1_47_778869623.dbf thread=1 sequence=47
media recovery complete, elapsed time: 00:00:01
Finished recover at 15-APR-12


ORACLE error from auxiliary database: ORA-19527: physical standby redo log must be renamed
ORA-00312: online log 1 thread 1: '/home/oracle/app/oradata/orcl/redo01.log'

RMAN-05535: WARNING: All redo log files were not defined properly.
ORACLE error from auxiliary database: ORA-19527: physical standby redo log must be renamed
ORA-00312: online log 2 thread 1: '/home/oracle/app/oradata/orcl/redo02.log'

RMAN-05535: WARNING: All redo log files were not defined properly.
ORACLE error from auxiliary database: ORA-19527: physical standby redo log must be renamed
ORA-00312: online log 3 thread 1: '/home/oracle/app/oradata/orcl/redo03.log'


RMAN-05535: WARNING: All redo log files were not defined properly.
Finished Duplicate Db at 15-APR-12
---------------------------------------------------------------

以上创建完成了物理standby数据库(最后的错误警告信息可以忽略,我们在后面的附录1详细解释这个错误信息)。但是备库数据库还没有开始应用redo log。

12. 创建standby redo log,standby redo log大小等于主库online redo log大小:
ALTER DATABASE ADD STANDBY LOGFILE GROUP 11
   ('+data/redo_sb_01.log') SIZE 52428800;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 12
   ('+data/redo_sb_02.log') SIZE 52428800;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 13
   ('+data/redo_sb_03.log') SIZE 52428800;
ALTER DATABASE ADD STANDBY LOGFILE GROUP 14
   ('+data/redo_sb_04.log') SIZE 52428800;

13. 运行下面的命令开始应用redo log:
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;


以上的全部步骤就配置完成了物理standby数据库,并且开始应用redo log。

附录1
----------
在创建备库时最后报出的错误警告信息ORA-19527和在MRP开始应用redo log时,alert log中报出下面的错误信息:

Errors in file /u01/app/diag/rdbms/orabak/orabak/trace/orabak_mrp0_7644.trc:
ORA-00313: open failed for members of log group 1 of thread 1
ORA-00312: online log 1 thread 1: '/home/oracle/app/oradata/orcl/redo01.log'
ORA-27037: unable to obtain file status
Linux Error: 2: No such file or directory
.....
Errors in file /u01/app/diag/rdbms/orabak/orabak/trace/orabak_mrp0_7644.trc:
ORA-19527: physical standby redo log must be renamed
ORA-00312: online log 1 thread 1: '/home/oracle/app/oradata/orcl/redo01.log'

以上错误的原因:
oracle为了加快备库与主库switchover的速度,从10.2开始增加了一个增强的功能,就是当MRP启动时会去清理备库上online redo log。造成以上2个错误有2个原因,第一个是备库没有创建online redo log,第二个是备库没有设置log_file_name_convert参数。

解决方法:
方法#1:如果不考虑switchover(备库上不创建online reod log),那么可以忽略这个错误,因为这个错只是一个提示性的信息,不会影响备库的MRP的工作。
方法#2:如果考虑switchover,在备库上创建online reod log,并且设置log_file_name_convert参数:
SQL> shutdown immediate;
SQL> startup mount;
SQL> ALTER DATABASE ADD LOGFILE GROUP 4 ('+DATA/redo01.log') SIZE 52428800;
SQL> ALTER DATABASE ADD LOGFILE GROUP 5 ('+DATA/redo02.log') SIZE 52428800;
SQL> ALTER DATABASE ADD LOGFILE GROUP 6 ('+DATA/redo03.log') SIZE 52428800;
SQL> alter system set log_file_name_convert='/home/oracle/app/oradata/orcl','+data' scope=spfile;
SQL> shutdown immediate;
SQL> startup mount;
SQL> ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;


11g 新特性 Member Kill Escalation 简介


    首先我们介绍一下历史。在oracle 9i/10g 中,如果一个数据库实例需要驱逐(evict, alert 文件中会出现ora-29740错误)另一个实例时,需要通过LMON进程在控制文件(以下简称CF)中写入相应信息,当目标实例的LMON进程读取到相应的信息后,该实例shudown。但是,如果目标实例的LMON进程挂起而无法完成CF I/O的话,eviction将无法成功,这种情况有可能导致整个数据库挂起,需要dba手工干预。
    所以,从oracle 11gR1 开始,Member Kill Escalation的出现成功的解决了前面提到的情况。当实例eviction在指定的时间内(默认20秒)不能成功完成时,oracle会在css层面上(因为lmon进程会作为成员注册到css上,相应的内容会在今后的文章中介绍)产生一个新的进程 Kill Daemon(以下简称KD), 终止目标实例的LMON进程以保证eviction 能够成功结束。如果情况更糟,KD进程也无法在指定的时间内(默认30秒)终止LMON进程,css 会把member kill升级为node kill,目标节点的css会重新启动本节点,以确保数据库的一致性。当然,如果您的版本是11.2.0.2或更高,由于新特性Rebootless restart的引入,node kill首先会尝试重新启动GI stack,如果不能够完成,才会重新启动节点。
    接下来我们用下面的例子说明Member Kill Escalation是如何工作的。
1.实例2发现实例1的LMS1进程出现问题,并发出member kill request.
实例2 Alert log:
Sat Jul 24 10:37:37 2010
LMS1 (ospid: 22636) has detected no messaging activity from instance 1
LMS1 (ospid: 22636) issues an IMR to resolve the situation
Please check LMS1 trace file for more detail.
Sat Jul 24 10:37:37 2010 <======= 实例2发出reconfiguration请求
Communications reconfiguration: instance_number 1
Sat Jul 24 10:38:25 2010
Evicting instance 1 from cluster
Waiting for instances to leave:
1
Sat Jul 24 10:38:45 2010 <===== 在reconfiguration请求发出20秒之后实例1仍然没有离开集群,实例2发出了member kill的请求。
Remote instance kill is issued with system inc 10
Remote instance kill map (size 1) : 1
Sat Jul 24 10:38:55 2010
Waiting for instances to leave:
1

2. 节点2的ocssd.bin收到member kill请求之后,向节点1的KD发出了请求,要求终止节点1的lmon进程。
节点2 ocssd.log:
2010-07-24 10:38:45.112: [    CSSD][1091119424]clssgmExecuteClientRequest: Member kill request from client (0x2aaab4178470)
2010-07-24 10:38:45.113: [    CSSD][1091119424]clssgmReqMemberKill: Kill requested map 0x00000001 flags 0x2 escalate 0xffffffff <========= member kill escalation还没有发生。
2010-07-24 10:38:45.113: [    CSSD][1281349952]clssgmMbrKillThread: Kill requested map 0x00000001 id 2 Group name DBOR08P flags 0x00000001 start time 0x98117058 end time 0x9811e77c time out 30500 req node 2 <======= member kill 需要在30秒内完成。

如果节点1能够在指定的时间内(30秒)终止本地lmon进程,member kill 就不会被escalation 成为node kill。

3.由于member kill 没有在指定的时间内完成,被escalate 为node kill,即节点1 重启。
节点2 ocssd.log:
2010-07-24 10:39:15.619: [    CSSD][1281349952]clssgmMbrKillThread: Time up: Start time -1743687592 End time -1743657092 Current time -1743657092 timeout 30500
2010-07-24 10:39:15.619: [    CSSD][1281349952]clssgmMbrKillThread: Member kill request complete.
2010-07-24 10:39:15.619: [    CSSD][1281349952]clssgmMbrKillSendEvent: Missing answers or immediate escalation: Req member 1 Req node 2 Number of answers expected 0 Number of answers outstanding 1
2010-07-24 10:39:15.620: [    CSSD][1281349952]clssgmMbrKillEsc: Escalating node 1 Member request 0x00000001 Member success 0x00000000 Member failure 0x00000000 Number left to kill 1
2010-07-24 10:39:15.620: [    CSSD][1281349952]clssnmKillNode: node 1 (ghlx062ptlge) kill initiated <====== 节点1被重启

注意:member kill escalation不仅适用于database 实例,同时也适用于ASM实例。

星期六 三月 31, 2012

11g 新特性:Active Data Guard

  在Oracle 11g之前,物理备库(physical Standby)在应用redo的时候,是不可以打开的,只可以mount。从11g开始,在应用redo的时候,物理备库可以处于read-only模式,这就称为Active Data Guard 。通过Active Data Guard,可以在物理备库进行查询或者导出数据,从而减少对主库的访问和压力。

   Active Data Guard适用于一些只读性的应用,比如,有的应用程序只是查询数据,进行一些报表业务,不会产生redo数据,这些应用可以转移到备库上,避免对主库资源的争用。


 Oracle Active Data Guard 是Oracle Database Enterprise Edition的一个功能,需要额外付费来使用这个功能。

   如需启用Active Data Guard, 只需要将备库以 read-only 模式打开,而且执行 ALTER DATABASE RECOVER MANAGED STANDBY DATABASE语句就可以。需要注意的是:主库和备库的COMPATIBLE 参数至少要设置为11.0.0。


   如下:在备库执行:  
   SQL>startup mount;
   SQL>alter database open read only;
   SQL>ALTER DATABASE RECOVER MANAGED STANDBY DATABASE DISCONNECT FROM SESSION;


  如果已经启用了Active Data Guard,备库的V$DATABASE会显示为"READ ONLY WITH APPLY':

      SQL> SELECT open_mode FROM V$DATABASE;
      OPEN_MODE
      --------------------
      READ ONLY WITH APPLY


  注意:使用Active
Data Guard
要求主库和备库的COMPATIBLE 参数至少设置为11.0.0


  为了保证备库数据的实时性,需要在备库启动real-time apply:
   SQL>ALTER DATABASE RECOVER MANAGED STANDBY DATABASE USING CURRENT LOGFILE;

  下面的功能是允许在read-only的数据库上执行的:
    • Issue SELECT statements, including queries that require multiple sorts that leverage TEMP
segments
    • Use ALTER SESSION and ALTER SYSTEM statements
    • Use SET ROLE
    • Call stored procedures
    • Use database links (dblinks) to write to remote databases
    • Use stored procedures to call remote procedures via dblinks
    • Use SET TRANSACTION READ ONLY for transaction level read consistency
    • Issue complex queries (such as grouping SET queries and WITH CLAUSE queries)

  下面的功能是不允许在read-only的数据库上执行的:
    • Any DMLs (excluding simple SELECT statements) or DDLs
    • Query accessing local sequences
    • DMLs to local temporary tables

    比较典型的Active Data Guard 分为:
  • 单实例的物理主库和单实例的物理备库
  • 主库为Oracle Real Application Clusters (Oracle RAC) ,备库为单实例
  • RAC主库和RAC备库

    Oracle Data Guard 的配置方法,,请参考下面的文档:


   * 单实例的物理主库和单实例的物理备库:
     http://docs.oracle.com/cd/B28359_01/server.111/b28294/create_ps.htm

  * 主库为Oracle Real Application Clusters (Oracle RAC) ,备库为单实例:
     http://www.oracle.com/technetwork/database/features/availability/maa-wp-10g-racprimarysingleinstance-131970.pdf

 * RAC 主库和RAC 备库:
   10g: http://www.oracle.com/technetwork/database/features/availability/maa-wp-10g-racprimaryracphysicalsta-131940.pdf
   11g: http://www.oracle.com/technetwork/database/features/availability/dataguard11g-rac-maa-1-134639.pdf

* 关于Active Data Guard的最佳实践经验,请参考文档:
    http://www.oracle.com/technetwork/database/features/availability/maa-wp-11gr1-activedataguard-1-128199.pdf


* 关于Oracle Maximum Availability Architecture Best Practices的更多文档,请参考:
   http://www.oracle.com/goto/maa


About

本博客由Oracle全球技术支持中国区的工程师维护。为中文用户提供数据库相关的技术支持信息,包括常用的诊断工具、诊断方法、产品新特性、案例分析等。此外,MOS也陆续推出各类中文内容:技术通讯统一发布在Note 1529795.1 中,中文文档列表更新在Note 1533057.1 中,网上讲座请查看MOS文档 1456176.1,在"Archived"中可以下载历史的录音和文档。

Search

Archives
« 四月 2014
星期日星期一星期二星期三星期四星期五星期六
  
1
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
今天