Oracle RAC学习笔记01-集群理论
写在前面:
最近一直在看张晓明的大话Oracle RAC,真实感受就是学到很多之前自己都没深入思考研究过的知识点,现在趁着节前头脑尚清醒,再结合实际工作中自己曾遇到的一些案例,就把这段时间自己学到的东西总结一下。
1.集群相关理论概述
一个集群(cluster)由2个或多个节点(nodes)组成。一般集群对外都会有统一的服务接口(集群地址),对内需要(集群内部通信)不断确定集群内部节点可用,一旦发生异常,可以通过(集群仲裁)驱逐问题Partition,使得集群能够不影响整体对外提供服务。
集群系统的设计一般都需要考虑2个经典问题:健忘和脑裂。
健忘:集群的配置文件,集群中各节点需要保证集群配置文件的一致性;
Oracle Clusterware集中记录这些信息到OCR,且整个集群只保留一份配置,各节点共用这份配置,解决了健忘的问题。
脑裂:集群内节点心跳通信故障时,集群需要决定具体哪个partition被踢出集群。
Oracle Clusterware采用两种心跳机制:网络心跳和磁盘心跳;当通过私有网络的网络心跳故障,需要使用voting disk的磁盘心跳来仲裁Partition剔除。
脑裂问题紧接着还涉及一个IO Fencing问题,即需要保护数据不被故障节点所修改破坏。RAC使用oprocd进程实现IO Fencing。
为了便于学习和理解,将RAC环境分为 存储层、网络层、集群层、应用层 4层来分别学习。
存储层
由SAN组成的存储层,由于RAC架构是共享存储,常规场景下只需要有一个存储。
但如果预算充足,为了进一步提高可用性,我们完全可以在存储层考虑使用2个存储,在存储层构建一个存储层面的集群。比如使用EMC的vplex,HDS的GAD(Global-Active Device)等。
这种存储级别的集群,在extended RAC架构中很常见。这一块基本都偏向于底层存储层面的知识,与RAC本身关系不大,不再多说。
网络层
public IP:集群各节点真实IP地址,和其他应用服务器连接在一个交换机上。
10g RAC VIP:在Public IP所在网卡上绑定一个VIP。
优点是:VIP是浮动的,使用VIP,可以避开对TCP协议栈超时的依赖。
11g RAC SCAN IP:在 VIP 基础上 再引入的scan IP,也有对应的scan IP的监听。
优点是:使用scan IP配置客户端连接,以后集群内部添加删除节点,不需改动客户端的tns配置。
private IP:集群内部互联IP,大数据量、低延迟要求,预算低用G级以太网,预算高用infiniband。
网络心跳(Network Heartbeat)使用这个private IP网络。
缓存融合(Cache Fusion)也是通过这个private IP网络进行传输。
集群层
集群层是在OS kernel和应用之间的一层。用来统一协调集群内各节点正常调度有序工作。
10g RAC 通过Oracle Clusterware来实现这一层的功能。
11g RAC 改名clusterware为GI。
GI除了名字上的不同,还有很多改变,比如将ASM安装的集成到GI中,比如GI的安装一般建议单独用户(grid)安装,而之前clusterware一般都是和数据库在同一用户(oracle)安装的等等,可以简单认为GI比clusterware更加完善细化了。
应用层
应用层是指在集群件之上的具体应用和资源。
RAC 按照用途主要把应用层分为2大类:nodeapps(节点应用) 和 database-related resource(数据库资源)。
nodeapps:GSD、ONS、VIP、Listener等。
database-related:Database、Instance、Service等。
2.Oracle Clusterware
Oracle Clusterware是Oracle自己开发的能支持所有平台的集群件,现在市场上还主要是用于RAC。
它的运行环境由两个磁盘文件、若干后台进程以及网络元素组成。
2.1 磁盘文件
两个磁盘文件,即OCR和Voting disk。
在10g RAC中,这两个文件必须放在真正的裸设备上,不可以放在ASM中。
在11g RAC中,这两个文件可以放在ASM上。
OCR:
负责维护整个集群的配置信息,包括RAC以及Clusterware资源,包括节点成员、数据库、实例、服务、监听器、应用程序等。
Voting disk:
存放在共享存储上,在集群出现“脑裂”时,仲裁哪个Partition最终获得集群的控制权。
2.2 后台进程
大家都知道的Clusterware最重要的进程:
CSS:管理集群内节点
CRS:管理集群资源
EVM:管理事件通知
我们具体来看clusterware中的主要后台进程:
ocssd: 用来管理集群内节点的加入/踢除。这个进程是clusterware中最关键的进程,如果该进程出现异常,会导致系统重启。
oprocd: 用来实现IO Fencing,早期Linux平台,使用hangcheck-timer模块来实现IO Fencing,从10.2.0.4开始,Linux平台也使用oprocd进程。
oclsomon: 用来监控css进程,如果发现进程挂起,会重启节点。
crsd: 用来管理集群内资源,是实现HA的主要进程。负责管理注册应用的start、stop、monitor、failover。
racgwrap脚本:CRSD会使用这个脚本来启动、关闭、检查实例的状态。
evmd: 负责发布CRS产生的各种事件。
racgimon: 用来监控集群健康状态,负责Service的启动、停止、故障转移。
2.3 网络元素
Oracle TAF是建立在VIP技术之上的。
TAF(Transparent Application Failover):对应用透明的故障转移。
文章前面在网络层概述提到过:VIP是浮动的,使用VIP,可以避开对TCP协议栈超时的依赖。
原因是:
TCP/IP实际的四层模型从下到上依次为:网络接口层(MAC)、网络层(IP)、传输层(TCP)、应用层(Listener)。
Public IP 和 VIP都属于网络层。
而当节点异常,对应的VIP会飘到其他节点,而其他节点没有该VIP地址的监听。VIP利用应用层的立即响应,避开对TCP协议栈超时的依赖。
3.Oracle RAC 原理
抛砖引玉:
GCS、GES、GRD、PCM这些东西是如何堆砌在一起的?
RAC的HA、LB、Cache Fusion...
3.1 数据库基本原理
数据库基本原理:同时保证并发和数据一致性。
1) 隔离级别
SQL-92标准中定义了四个隔离级别:Read Uncommitted、Read committed、Repeatable、Serializable。
Oracle 默认实现read committed隔离级别而不影响并发;这也曾是Oracle比较得意的地方。
2) 锁
数据库系统使用“锁”来控制“并发”。
Lock:代表一种控制机制,Lock框架包含3个组件:Resource Structure(资源)、Lock Structure(锁)、Enqueue(排队机制)。
Row-Level Lock:对于“数据记录”这种细粒度资源,Oracle使用的是行级锁。
行级锁共涉及以下4种数据结构:
ITL:块头ITL,用于记录哪些事物修改了这个数据块的内容,可以把它想成一个表格,每行记录一个事物,包括事物号、事物是否提交等重要信息。
记录头ITL索引:每条记录的记录头部有一个字段,用于记录ITL表项号,可以看作是指向ITL表的指针。
TX锁:这个锁代表一个事物,属于Lock机制。
TM锁:属于Lock机制,用于保护对象的定义不被修改。
无论一个事物修改多少个表的多少条记录,该事物真正需要的只是一个TX锁,每个表一个TM锁,内存开销非常小。而所谓的“行级锁”只是数据块头、数据记录头的一些字段,不会消耗额外资源。
因此,对于Oracle的“行级锁”必须要有正确的理解,它不是Oracle中通常意义上的“锁”,虽然有锁的功能,但是没有锁的开销。
Latch: Latch请求,获得,释放等操作是原子操作,一般几个硬件指令就可以完成。是一种低级锁,主要用于保护数据结构。
也就是说如果请求Latch得不到,不会释放CPU资源,而会不断尝试请求,只有在一定次数还不能获得时,才释放CPU。这就是Latch的spin机制。
锁模式:
- --官方文档中v$lock中LMODE取值
- 0 - none
- 1 - null (NULL)
- 2 - row-S (SS)
- 3 - row-X (SX)
- 4 - share (S)
- 5 - S/Row-X (SSX)
- 6 - exclusive (X)
-
- --手工加锁语句语法参考
- lock table &table_name in [ROW] SHARE, [[SHARE] ROW] EXCLUSIVE, SHARE UPDATE
-
- --2 - row-S (SS)
- lock table t_second_p in row share mode;
- lock table t_second_p in share update mode;
- --3 - row-X (SX)
- lock table t_second_p in row exclusive mode;
- --4 - share (S)
- lock table t_second_p in share mode;
- --5 - S/Row-X (SSX)
- lock table t_second_p in share row exclusive mode;
- --6 - exclusive (X)
- lock table t_second_p in exclusive mode;
-
- --查看被锁的对象
- select * from v$locked_object;
3) SQL语句执行过程:
用户发出一条SQL语句,将主要经过解析、优化、产生执行计划、返回执行结果几个阶段。
如果解析后发现,在shared pool中已经有对应的执行计划,就可以直接拿来使用,相当于跳过了中间优化、产生执行计划2个步骤,这就是软解析。
这个过程中对Lock和Latch的使用:
前三个阶段目的就是产生执行计划,所谓“执行计划”就是对应shared pool中一个复杂的数据结构。
a. 为了产生这个数据结构,Oracle要计算SQL语句的哈希值,根据这个值确定要检索的“桶“(Hash Bucket),然后遍历这个桶中的”链表“,看是否有相同的SQL语句。如果没有,就要进行硬解析。
进程要从shared pool空闲空间中申请一块空间,用来存放编译后的执行计划。这就需要检索另一个”空闲链表“,从中申请一个大小合适的空闲块,申请成功后要更新这两个链表。在这个过程中,至少
涉及两个数据链表的访问,这个访问是”排他“(exclusive)的,不允许其他进程同时修改乃至访问,这就需要对”链表“加锁,这种锁用的就是Latch机制。b. 在语句编译和执行过程中,“引用对象”的结构不能被更改。在编译前,需要把表的”元数据“加载到内存,在随后编译和执行过程中,这个内容保持不变,也就是不能让其他用户改变这个表的结构。
这里使用的就是TM Lock。c. 执行阶段,要在buffer cache中定位到数据块,同样根据数据块地址查找“桶”中的“链表”找到最终的数据块。在这个过程中,链表数据结构也不能被修改,同样是使用latch保护。访问数据块
中的记录时,也要限制其他进程的访问,使用的是行级锁进行保护。
3.2 RAC环境并发控制
1) DLM、Cache Fusion、Non-Cache Fusion
由于要解决多个节点的并发,所以额外引入了DLM(Distribute Lock Management)。
DLM在Oracle发展的不同时期,名字也不相同,在OPS时期,叫做PCM;而在RAC时期叫做Cache Fusion。
在RAC中,DLM是以数据块作为粒度单位进行协调。
DLM协调集群各节点对资源使用的功能就叫做同步。在DLM中,根据资源数量、活动密集程度将资源分成了两类:PCM Resource、Non-PCM Resource。[也称Cache Fusion Resource、Non-Cache Fusion Resource]
对应两种资源,DLM提供的锁也是两种:PCM Lock、Non-PCM Lock。[也称Cache Fusion Lock、Non-Cache Fusion Lock]
在RAC数据库中共有两大类四种锁:
Local Lock:用于本地进程的并发控制,就是与传统单实例一样的,Latch 和 Lock。
Global Lock:用于集群间的并发控制,就是 PCM Lock 和 Non-PCM Lock。
典型的Non-Cache Fusion资源就是row cache和library cache。
PCM Lock 有三种模式,分别对应SGA中数据块的状态如下:
- PCM Lock Mode Buffer state
- X XCUR
- S SCUR
- NULL CR
2) GRD
Cache Fusion要解决的首要问题是:数据块拷贝在集群节点间的状态分布图。RAC是通过GRD来实现的。
GRD位于每个实例的SGA中,所有实例的GRD汇总在一起才是一个完整的GRD。
GRD中记录的是PCM Lock信息,这种锁有三个属性:Mode、Role、PI。
Mode:X、S、NULL。
Role:L和G。
PI:Past Image主要能够加速Crash Recovery的恢复过程。
书中模拟一个场景:4节点RAC,针对一个数据块,这个数据块的Master node是节点2。PCM Lock用ModeRolePastimage格式描述,比如SL0代表Share Mode、Local Role、0个Past Image。
分别对并发读、读并发写、写并发写、写入磁盘、写并发读等情形,描述了集群相关节点的GRD、PCM Lock的变化过程,体会到Cache Fusion具体是如何工作的。限于篇幅,这里不再赘述。
总之,无论是单实例还是RAC,实例要修改数据块,必须获得这个数据块的当前版本。
3.3 RAC架构
1) SGA的变化
多了一个GRD(Global Resource Directory)部分,GSD的功能前面已经说过。
2) 后台进程的变化
LMSn GCS(Global Cache Service),这个进程是Cache Fusion的主要进程,负责数据块在实例间的传递。
LMD GES(Global Enqueue Service),这个进程负责在多个实例之间协调对数据块的访问顺序。它与LMSn进程的GCS服务还有GRD共同构成RAC最核心的功能Cache Fusion。
LCK 这个进程负责Non-Cache Fusion资源的同步访问。
LMON 各个实例等LMON进程会定期通信,检查集群中各节点的健康状态。负责集群重构、GRD恢复等操作,它提供的服务叫做CGS(Cluster Group Services)。
LMON提供节点监控功能:通过一个保存在GRD中的位图来记录(0代表节点关闭,1代表节点正常);
LMON检测到实例级别的“脑裂”时,会通知clusterware解决,如果等待超时,LMON进程会自动触发IMR(Instance Membership Recovery)。
LMON进程提供的IMR功能可以看作是Oracle在数据库层提供的“脑裂”,“IO隔离”机制。(LMON也借助两种心跳:网络心跳、控制文件的磁盘心跳)。
DIAG DIAG监控实例的健康状态,并在实例运行错误时收集诊断数据到Alert.log日志中。
GSD GSD进程负责从客户端工具,比如srvctl接收用户命令,为用户提供管理接口。
3) 文件
spfile 需要被所有节点访问,存放在共享存储上。
redo thread 每个实例都需要自己的一套redo log。需要被所有节点访问,存放在共享存储上。
archived log 建议存放在共享存储上。当然也有其他设计方式。
undo tablespace 每个实例都需要有一个单独的回滚表空间。存放在共享存储上。
4) SCN
在RAC中,由GCS负责全局维护SCN的产生,ORACLE 10g RAC 缺省使用的是Broadcast算法,可以从alert.log中看到。
5) Cache Fusion、GCS、 GES
GCS负责数据块在实例间的传递;
GES负责锁管理。
3.4 RAC和Clusterware的交互
RAC集群和节点集群是两个层次的集群,两个集群都有脑裂、IO隔离等问题。
两个集群有各自的故障检测机制,二者之间的机制可以有重叠也可以不同。
在RAC这一层出现节点故障时,首先会通知clusterware这种异常,等待clusterware完成集群重构,完成后再通知RAC,RAC集群再开始自己的重构,但是RAC并不完全依赖于clusterware解决问题,如果发生等待超时,RAC的LMON进程会自动触发IMR执行节点排除。
Reference
- 张晓明. 大话Oracle RAC[M]. 人民邮电出版社, 2011.
- 张晓明. 大话Oracle Grid[M]. 人民邮电出版社, 2014.