ORACLE RAC 原理

xiaoxiao2021-07-06  401

RAC原理

rac中每个节点有自己的redo、undo、控制文件、参数文件。所有节点共同访问共享磁盘阵列(ASM RAW OCFS2),通过内存中的GRD资源、GCS资源和LMS、LCK进程来实现缓存融合技术,防止出现各节点对同一个数据块的争用和锁争用。

rac中存在公网、私网,使用过公网IP对各节点进行负载均衡,避免单点故障,各节点通过私网进行信息实时同步,并通过私网心跳机制,每隔3秒对节点进行探测,实时剔除死掉的节点。并对剩余节点进行重新负载均衡。

在单机oracle中主要进程为 DBWN LGWR PMON SMON ARCH CKPT等进程

在 oracle rac中主要进程为 DBWN LGWR PMON SMON ARCH CKPT LMS LMD LCK LMON DIAG 等进程,同时cluster weare 中还有CRSD、OCSSD、EVMD和ONS等进程用于集群资源交互。

 

RAC相关后台进程

-RAC资源-

 

GRD (Golabl Resource Directory):存在于SGA中的shared pool中,用来记录不同实例中锁的状态,在不同的实例之间有一个通信的网络--私网,GRD的信息可以通过私网分享到别的实例,实现不同实例间的操作。GRD内存块主要是记录此rac有多少个集群数据库与系统资源,同时也会记录数据块的相关信息,因为在 rac 架构中,每个数据块在每一个 SGA 中都有一份副本,而 rac 必须知道这些数据块的位置,版本,分布以及目前的状态,这些信息就存放在 GRD 中,但 GRD 只负责存放不负责管理,(内存融合)

 

GES :全局队列服务(GES)主要负责维护字典缓存和库缓存的一致性。字典缓存是实例的 SGA 内所存储的对数据字典信息的缓存,用于高速访问。由于该字典信息存储在内存中,因而在某个节点上对字典进行的修改(如DDL)必须立即被传播至所有节点上的字典缓存。GES 负责处理上述情况,并消除实例间出现的差异。处于同样的原因,为了分析影响这些对象的 SQL 语句,数据库内对象上的库缓存锁会被去掉。这些锁必须在实例间进行维护,而全局队列服务必须确保请求访问相同对象的多个实例间不会出现死锁。LMON、LCK 和 LMD 进程联合工作来实现全局队列服务的功能。GES 是除了数据块本身的维护和管理(由 GCS 完成)之外,在 RAC 环境中调节节点间其他资源的重要服务。为了保证集群中的实例的同步,两个虚拟服务将被实现:全局排队服务(GES),它负责控制对锁的访问。

 

GCS:全局内存服务(GCS),控制对数据块的访问。GES 是分布式锁管理器(DLM)的扩展,它是这样一个机制,可以用来管理 oracle 并行服务器的锁和数据块。在一个群集环境中,你需要限制对数据库资源的访问,这些资源在单 instance 数据库中被 latches 或者 locks 来保护。比如说,在数据库字典内存中的对象都被隐性锁所保护,而在库高速缓存中的对象在被引用的时候,必须被 pin 所保护。在 RAC群集中,这些对象代表了被全局锁所保护的资源。GES 是一个完整的 RAC 组件,它负责和群集中的实例全局锁进行沟通,每个资源有一个主节点实例,这个实例记录了它当前的状态。而且,资源的当前的状态也记录在所有对这个资源有兴趣的实例上。GCS是另一个 RAC 组件,负责协调不同实例间对数据块的访问。对这些数据块的访问以及跟新都记录在全局目录中(GRD),这个全局目录是一个虚拟的内存结构,在所有的实例中使用扩张。每个块都有一个master实例,这个实例负责对GSD的访问进行管理,GSD里记录了这个块的当前状态信息。GCS是 oracle 用来实施 Cache fusion(内存融合) 的机制。被 GCS 和 GES 管理的块和锁叫做资源。对这些资源的访问必须在群集的多个实例中进行协调。这个协调在实例层面和数据库层面都有发生。实例层次的资源协调叫做本地资源协调;数据库层次的协调叫做全局资源协调。

 

--设备需存放在共享磁盘阵列中,供各个节点访问

OCR:Oracle Clusterware 在 OCR 中存放集群配置信息,所有对 OCR 的操作必须确保OCR 内容完整性

VOTE :Voting Disk 这个文件主要用于记录节点成员状态,在出现脑裂时(区别HA),决定哪个 Partion 获得控制权,其他的Partion 必须从集群中剔除

 

################################################################################

RAC 服务器进程

 

在RAC中,由于有多个实例存在,所以不能使实例直接访问共享存储,需要通过中间架构(CRS服务层)来对实例请求处理。其中服务层包括多种服务(CRS- 集群资源服务、CSS - 集群同步服务、EVMD 事件管理服务、ONS--事件的发布及订阅服务)

 

CRSD(Cluster Ready Services 集群资源服务):负责集群的高可用操作,管理的 crs 资源包括数据库、实例、监听、虚拟 IP,ons,gds 或者其他,操作包括启动、关闭、监控及故障切换。改进程由 root 用户管理和启动。crsd 如果有故障会导致系统重启。

cssd(Cluster Synchronization Service 集群同步服务):管理各节点的关系,用于节点间通信,节点在加入或离开集群时通知集群。该进程由 oracle 用户运行管理。此进程故障会导致集群重启

evmd(Event Management 事件管理服务):事件管理检测进程,由 oracle 用户运行管理

ONS(Oracle Notification Service 事件的发布及订阅服务):通信的快速应用通知事件的发布及订阅服务

 

###############################################################################

 

rac实例核心进程

 

 

-----RAC实例中管理锁的进程

LMS(Gobal Cache Service Process,全局缓存服务进程):RAC核心进程,处理全局缓存(实例间数据交换进程),主要负责完成GCS的大部分工作,它会维护GRD中数据块资源的信息,完成数据块在实例之间的传递工作,相关消息的发送和接收工作。每个数据库实例中会存在多个LMS进程,名称为LMS<x>,默认的LMS进程数量是根据节点的CPU数量计算出来的。(缓存融合核心进程)

 

LCK0(Instance Enqueue Process 实例查询进程):这个进程主要负责实例锁(实例锁的含义并不是实例级别的锁,而是指这种锁管理的资源仅限于本地实例)管理,实例级别的锁包括:library cache lock,row cachelock等,实例级别的锁是由LCK进程通过广播的方式进行管理的,当一个进程需要持有一个实例锁时,LCK进程会以广播方式向所有远程实例的LCK进程发送这个请求,而远程实例收到这个请求之后,更新自己的信息并反馈信息(如果远程实例的某个进程以不兼容的方式持有了这个锁,对应实例的LCK进程会通知持有者进程释放对应的锁,然后再返回),每个实例默认情况下只包含一个LCK进程。

 

-----rac实例中多出的进程

LMD(Global Enqueue Service Daemon 全局查询服务守护进程):主要管理对全局队列和资源的访问,负责GES相关资源的管理工作,并更新相应队列的状态,处理来自于其他实例的资源请求。每一个全局队列的当前状态存储在相应的实例共享内存中,该状态表明该实例具有相应的权利使用该资源。一个实例(master,1节点)的共享内存中存在一个特殊的队列,该队列纪录来自其他远程实例的资源请求,当远程实例(2节点)的LMD进程发出一个资源请求时,该请求指向master实例(1节点)的LMD,当master实例(1节点)的LMD进程受到该请求后,在共享内存中的特殊队列中监测该资源是否有效,如果有效则LMD进程更新该资源对列的状态,并通知请求资源(2节点)的LMD进程该资源队列可以使用了,如果资源队列正在被其他实例使用或者当前无效,则LMD进程通知正在使用中的实例的LMD进程应该释放该资源,等资源释放变得有效时,MASTER实例的LMD进程更新该资源队列的状态并通知请求资源实例的LMD进程该资源队列可以使用了。

 

DIAG(Diagnostic Daemon 诊断守护进程):Oracle10g新的后台进程。例行对实例的健康情况进行监控,同时也监控实例是否挂起或者出现死锁。收集实例和进程出错时的关键诊断信息。这个进程会更新alert日志文件,写入一些重要告警信息。

 

LMON(Lock Monitor Process,锁监控进程):实例间的LMON进程会定期通信,检查集群中各个节点的健康状况,当某个节点出现故障时,负责集群重构、GRD 恢复等操作,它提供的服务叫做 Cluster Group Service(CGS)。

 

LMON 主要借助两种心跳机制来完成健康检查。

节点间的网络心跳(Network Heartbeat):可以想象成节点间定时的发送 ping 包检测节点状态,如果能在规定时间内收到回应,就认为对方状态正常。

通过控制文件的磁盘心跳(controlfile heartbeat):每个节点的 CKPT 进程每隔 3 秒钟更新一次控制文件的数据块,这个数据块叫做Checkpoint Progress Record,控制文件是共享的,所以实例间可以互相检查对方是否及时更新来判断。

 

 

---缓存融合(cache fusion)

 

缓存融合是oracle RAC引入的一项技术,主要是通过LMS、LMD、LCK进程在多个实例之间进行信息交互,将每个节点的请求资源有序的分配并记录在GRD中,防止出现热点块。

当1节点在buffercache中正在读取一些data block(A),2节点需要对data block(A)进行操作,

当1节点在读取该数据块时首先产生lock 并将该信息记录在GRD中,当2节点请求访问,首先需要通过LMD 请求1节点释放资源,然后通过LSMn进程请求1节点锁,释放锁2节点在持有锁(这里不研究锁)并将信息再次记录在GRD中并通过LMS进程copy一份信息记录到另一个节点的GRD中,其中所有的修改都会在所有节点的GRD中进行修改,过程中的所有锁由该进程的LCK进程进行管理,避免出现锁争用。

 

ORACLE中是通过SCN来保证数据连续性的,在RAC中,SCN内引入内存融合,多个节点同时对数据库修改数据时,在数据库层面对数据的修改永远是串行的。

 

无数据传输模式的读取

数据块在磁盘上,不是在内存中。

实例2要读取一个数据块的时候,每次去请求一个资源的时候,就要申请锁,只有获得锁才能被允许访问数据块,如果请求的时候发现数据块被别人持有了,那么就不能获得访问数据块的权限,就要处于等待。在RAC下就会经常出现GC的等待(GOLBAL CACHE全局内存资源的等待)。 

RAC中一个实例(实例2)去请求数据块的时候,在集群里面有一个resource master,即管理资源的,访问数据块的时候首先去resource master里面去申请锁(通过私网),因为是读数据块,所以是以一种共享锁的方式去请求,一旦申请成功之后就将共享锁赋予实例2,持有共享锁之后就可以去访问数据块了。现在这个数据块不在内存里面,而是在磁盘上面,那么就直接去磁盘上将数据块读取出来。

一个4节点 rac读到写操作的数据传输

现在实例2将磁盘上面的数据块读到内存里面了,现在实例1要去修改该数据块。

首先实例1因为要修改数据块,实例1将请求发送给GCS,GCS将请求发送给resource master申请排它锁,一旦将数据块放在实例2上面了,实例2就会将信息注册到resource master的GRD中在集群中共享,所以resource maste会知道数据块存在于实例2上面,由于实例1要修改的数据块在实例2上面,所以resource master会去通知实例实例2将数据块传输到实例1上面。因为实例2上面对数据块使用的是共享锁,那么要传输到实例1上面要使用排他锁,因为互斥,所以实例2要将共享锁释放。实例2将数据块的状态通知给实例1。在实例1拿到该数据块的时候将数据块的状态告诉给resource master。实例1要修改该数据块,那么就要在该数据块上面加上排他锁。

每一个实例申请到数据块之后,会将数据块状态汇报给resource master。即注册到里面,这样以便于使得resource master知道数据块的分布。即数据块所在的实例和锁的形式。

 

写到写的数据传输

现在实例1已经对要被修改的数据块持有排他锁了,并且对数据修改完了。实例4要修改该数据块.

实例1的数据块资源已经注册到resource master里面了,所以resource master知道实例4要修改的数据块在实例1上面。这个时候resource master会去通知实例1将上面的数据块的情况告诉给实例4,所以实例1将资源的状态告诉给实例4,之后实例1释放排他锁,这个时候 数据块在实例1上面就没有排他锁了,这个时候就可以将数据块拷贝到实例4上面了,实例4对该数据块加上排他锁,同时将实例4的状态注册到resource master里面去,最后就是修改数据了。

注:当实例1要将数据块传输给实例4的时候,实例1创建了一个脏数据的前映像。读是不需要创建一个前映像的,写是要创建的,这是因为要保证数据安全性。即将实例1上面的数据块创建一份备份拷贝到实例4上面。这样是防止实例4出现问题。

 

前映像--past image

实例1上面开始修改数据块了,最初数据块的值是1323,修改完为1324之后就提交了,每次修改之后都会产生undo和redo,最后修改完到1328了,此时有一个会话链接到实例2上,要将这个数据块改为1329,现在实例2上面还没有这个数据块,所以这个时候实例2要去以排他的方式去请求数据块,这个时候要从实例1上面将数据块拷贝到实例2上面,但是在拷贝1328这个数据块到实例2上面去之前要保留一个修改之前的镜像,即保留1328这个数据块在实例1上面。

为什么这样做,其实也就是在实例2出现故障的时候做实例恢复时候用的。1328数据块拷贝到实例2上面了,实例2开始修改,修改成为1329,同时产生undo和redo,修改完成为1329之后,做了一次提交,这个时候实例2上面的内存里面的redo就写到磁盘上面了,写到磁盘上面之后突然实例2就宕机了。这个时候实例2在还没有做检查点的时候就宕机,内存里面的数据就丢失了,修改的数据块在实例1和实例2的内存里面都没有写到磁盘上面,实例1一直修改数据块但是没有提交,但是实例2修改后提交了,宕机了。

在RAC里面一个实例挂了,其他实例还在工作,这个时候不需要数据库重启,只需要其他实例来接管就可以了,在各个实例里面,redo是放在共享存储里面的,就是每一个实例都可以访问其他实例里面的redo信息,也就是将提交的数据但是还没有写到磁盘上面的数据用宕机的redo日志来重新生成一遍。这个过程由其他实例来做,因为其他实例没有宕机。

之前在实例1上面构造的前映像1328,在实例2宕机之后读取实例2上面的redo日志,运用实例2上面的日志来修复实例1上面前映像。让其变为1329。

在RAC里面,redo是可以共享的,之所以允许实例互相访问就在于当某一个实例坏了,其他实例可以读取该实例的redo信息进行恢复。前映像就是利用宕机后实例的redo信息将数据块恢复到最新的状态。

写到读数据传输

实例4已经获得了数据块,并且以一种排他的方式来修改这个数据块了,现在实例2要来访问实例4上面的数据块,实例2上要以读的方式去访问数据块就需要获得共享锁,实例2还是要去resource master请求一个锁,但是请求的是一个share锁,之后resource master就会告诉实例所需的数据块在实例4上面,现在实例2请求的是share模式的锁,现在实例4并不需要将锁全部释放掉,因为一个资源上面可以加多个共享锁。 

某个实例要访问数据块一定要把数据块复制到本地,如果不在本地,那么有两种可能:①数据在磁盘上面,直接从磁盘上面将数据读取到内存,②数据块在别的内存里面,就要去另外一个实例的内存里面去请求,这里就要看数据块所在的实例加了什么样的锁,如果加的是排他锁,我们申请的是共享锁,那么就要等到锁释放了。

 

 

 

转载请注明原文地址: https://www.6miu.com/read-4821490.html

最新回复(0)