编者按:
本文作者系肖遥(花名),原甲骨文技术支持工程师 ,专注于Oracle RAC领域。个人主页:
https://blog.csdn.net/weixin_50510978,经其本人授权发布。
【免责声明】本号文章仅代表个人观点,与任何公司无关。
编辑|SQL和数据库技术(ID:SQLplusDB)
浅谈RAC系列:
浅谈Oracle RAC (1)--概要
浅谈Oracle RAC (2)--集群管理软件GI基本架构
浅谈Oracle RAC(3)--GI的启动
浅谈Oracle RAC(4)– OHAS组件
浅谈Oracle RAC(5)– CSS组件
浅谈Oracle RAC(6) 之实战:节点reboot问题的调查方法
浅谈Oracle RAC(7) -CRS组件
浅谈Oracle RAC(8) -OCR和投票盘
前面我们写了很多关于集群软件的知识,了解之前的内容,在维护RAC环境时是必不可少的技能。今天我们来写一些关于数据库层面的知识。
1.RAC DB 与 GI 的关系
正如之前我们谈到的GI软件是甲骨文开发的集群软件,这个集群软件可以管理众多资源。这里所说的资源包括各种应用程序(当然也可以包括客户自定义的程序)。在介绍CRS的博文中,我们介绍到GI软件中的CRS组件是管理资源的重要组件。它可以对资源进行 CHECK,START,STOP,ABORT 等操作。那么Oracle数据库当然也可以被GI所管理,Oracle数据库以ora.<数据库名>.db的资源名的形式存在于GI管理的资源中。我们通过以下命令可以看到CRSD下面所管理的Oracle数据库的名字。
代码语言:javascript复制# crsctl stat res ora.test.db -t
--------------------------------------------------------------------------------
NAME TARGET STATE SERVER STATE_DETAILS
--------------------------------------------------------------------------------
Cluster Resources
--------------------------------------------------------------------------------
ora.test.db
1 ONLINE ONLINE node2 Open
2 ONLINE ONLINE node1 Open
以上的例子说明TEST是个2节点的RAC数据库,其两个instance分别存在于node1和node2上。
以上除了STATE和STATE_DETAILS之外的信息都保存在OCR中。而STATE和STATE_DETAILS的信息则是由CRSD的oraagent监测到的当前TEST数据库的状态。
既然RAC DB被CRSD组件管理,那么我们可以通过GI层面的命令srvctl来操作RAC DB。比如:
代码语言:javascript复制$srvctl start|stop database -db <数据库名>
以上命令可以通过CRSD将所有节点的数据库启动和关停。为什么可以这样做?因为CRSD是一个在所有节点上都存在的分布式组件。
关于stop命令需要注意一点,在不指定关闭数据库的mode时,srvctl默认采用是immediate。也就是说srvctl内部会执行类似于shutdown immediate的命令。
如果你需要强制停止数据库时,可以在srvctl后面加-o abort.
代码语言:javascript复制$srvctl stop database -db <数据库名> -o abort
还有其它的操作mode,就不一一列举了。
另外,可以用以下命令启动或关闭特定节点上的实例。
代码语言:javascript复制$srvctl start|stop instance -db <数据库名> -node <节点名>
那么我们如何查看GI中登录的RAC DB的信息呢?我们可以用下面这个命令:
代码语言:javascript复制$ srvctl config database -d <db unique name>
Database unique name: <db unique name>
Database name: <db name>
Oracle home:<$ORACLE_HOME>
Oracle user: <username>
Spfile: < diskgroup>/dbname/filetype/spfile<db name>.<file>.<incarnation>
Password file: < diskgroup>/dbname/filetype/pwd<db name>.<file>.<incarnation>
Start options: open
Stop options: immediate
Database role: PRIMARY
Management policy: AUTOMATIC
Server pools:
Disk Groups: <DISKGPOUP1>,<DISKGPOUP2>...
Mount point paths:
Services: <SERVICE NAME>
Type: RAC
Start concurrency:
Stop concurrency:
OSDBA group: <group name>
OSOPER group:
Database instances: <instance1>,<instance2>,....
Configured nodes:<nodename1>,<nodename2>,...
Database is administrator managed
※这里面描述的spfile,pswfile等文件名则与ASM有关,等以后介绍ASM时再介绍。
从上面的命令我们能够看到保存在OCR中的数据库几个比较重要的信息是:
代码语言:javascript复制NUM 内容
1 数据库名(Database name)
2 Oracle home
3 Spfile的位置
4 密码文件的位置
5 关闭数据库的mode(Stop options)
6 数据库role(Database role)
7 Management policy
8 磁盘组(Disk Groups)
9 服务(Services)
10 数据库类型(Type)
11 数据库实例(Database instances)
12 实例所在节点(Configured nodes)
以上记载在OCR中的数据库信息与实际数据库真实信息不匹配时都会导致数据库启动不了等各种问题。
这里面经常出现问题的点是Oracle home,spfile位置,密码文件位置。特别是后两者,因为客户因测试等原因经常手动重做spfile,密码文件,结果重启数据库时发生无法启动现象。这个时候把上面的命令信息再自己检查一下,是不是GI知道的信息与您知道的信息不匹配。如果不匹配,可以用下面的命令去更改存储在OCR中的关于该数据库的信息。
代码语言:javascript复制$srvctl modify database -db <数据库名>
以上命令的详细用法可以通过以下命令获得帮助:
代码语言:javascript复制$srvctl modify database -h
另外Database role的信息在Dataguard中是非常有用的,有时候我们也需要用这个以上命令修改OCR中存储的主备库的role使之与实际匹配。
此外这里面需要注意的地方是,用srvctl config database命令确认到的磁盘组信息只表示与数据库强依赖关系的磁盘组。而什么样的磁盘组与数据库是强依赖关系呢?这个是由以下因素决定的。
代码语言:javascript复制1.srvctl modify database -d DB名 -a命令明确指定的磁盘组。
2.装有控制文件的磁盘组。
3.配置有REDO日志文件的磁盘组。
4.装有数据文件的磁盘组(tempfile除外)。
5.装有spfile的磁盘组。
那么装有归档日志和tempfile的磁盘组则默认是弱依赖关系。
2.RAC DB的启动和停止方法
在单实例的Oracle数据库中,我们通过命令startup,shutdown命令启动和关停数据库。在RAC DB中,以上命令仍然可以做到。不同的是RAC中,以上命令只能启动关停一个实例,而不是所有节点的实例。要想启动关闭RAC DB,需要到所有节点实例中执行命令。
另外Oracle官方推荐使用srvctl命令启动关闭数据库。主要原因有以下2点:
1.srvctl具有一定的权限修复功能。因为某些原因造成数据库软件文件权限出现变动时,使用srvctl命令启动是可以修复一定的问题文件的。
2.srvctl命令是通过CRSD来启动关停数据库的,所以一旦命令发出,GI是会立刻知道数据库要被启动或者停止。而startup和shutdown命令则是数据库层面的命令,早期版本的RAC中,这两个命令不会向CRSD通知数据库要启动关闭的信息,只能靠oraagent对DB的CHECK来检知,具有一定的延迟性。虽然高版本的RAC中,这个问题已经几乎看不见了,但是由于第一个原因,甲骨文官方仍然推荐使用srvctl命令。
在实际应用中,我还见过很多srvctl命令无法启动数据库,而startup却可以的案例。所以有时候我们需要知道srvctl命令更详细的处理信息。我们可以通过以下设定来得到srvctl在操作集群资源时更详细的信息。
在OS中设定下面的环境变量:
代码语言:javascript复制--- For Linux ----
$ export SRVM_TRACE=true
--- For Windows ---
>set SRVM_TRACE=true
然后执行srvctl 命令,这时在terminal或者prompt上便会输出详细的信息了。
另外在关闭数据库时有个特殊例子需要各位同学注意一下,在生产环境中,千万不要随便在没有关停数据库之前就通过crsctl stop crs让该节点的GI重启。因为crsctl stop crs命令在关停数据库资源时使用的是abort的模式。如果数据库中还有没处理完的transaction时,是被强制终止的。
正确的做法是:
代码语言:javascript复制1.关闭监听(srvctl stop listner)
2.关闭服务(srvctl stop service)
3.关闭数据库实例(srvctl stop instance)
4.关闭GI(crsctl stop crs)
3.如何调查RAC数据库宕机问题
调查RAC数据库宕机问题主要从三个方向来调查。
代码语言:javascript复制1.OS重启
2.GI重启
3.DB重启
经常遇到很多国内的DBA问我我的RAC数据库某个节点宕机原因,然后只把那个节点上的DB alert日志给我。我想说但凡遇到数据库宕机问题,千万不要只认为是数据库出了问题,因为有很多时候数据库也是受害者。
因为我们知道当OCSSD无法进行磁盘心跳或者网络心跳时,OCSSD会发起节点排除的动作,这时候GI或者OS会被重启。这时候自然DB会发生宕机现象。
另外因为OS资源不足会导致OCSSD夯住,此时的cssdagent
或者cssdmonitor也会发起OS重启命令,即便是cssdagent,cssdmonitor夯住,GI也会通过OS的kernel来将OS重启。
所以我们调查RAC DB重启时的顺序基本上是要配合OS的资源利用信息,先来查看GI的日志文件和OS日志。在确定并非GI或者OS自身的机制导致的重启问题之后,我们才会再去查看DB alert日志文件去查看是否有数据库的critical的进程发生某种error而宕机。
所以我们在调查这类问题时至少需要以下信息:
代码语言:javascript复制NUM 日志名
1 OS日志
2 OS资源利用信息(OSW收集的信息)
3 CRS alert日志
4 CRSD trace 文件
5 CRSD oraagent trace文件
6 DB alert日志
7 确定DB层面的问题时,需要对应的DB 进程trace文件
4.关于不期待的RAC数据库实例重启现象
有很多DBA说我想关停一个节点上的某个数据库实例,即便重启该节点的GI,也不希望这个节点的某个数据库实例资源跟着启动。于是,他用srvctl关停了这个节点的实例。可是当他重启GI后,这个节点的数据库实例仍然启动了。
所以这里我们总结一下造成这类问题的几个主要原因:
1.srvctl stop instance时,GI层面发生问题,导致OCR中并没有将 TARGET变成OFFLINE状态。所以在执行命令时,一定要用crsctl stat res -t命令确认好结果。
2.OCR中存储的该数据库资源属性AUTO_START被设定成了always。在CRSD的博文中,我们介绍了这个属性的三个设定值分别代表什么意思,感兴趣的小伙伴可以翻看浅谈RAC–CRSD那篇博文。
3.service等与DB资源有强依赖关系的资源属性中设定了与该数据库的pullup依赖关系。也就是说虽然DB实例资源本身不会随着GI的启动而启动,但是service等资源却被设定成了随CRS启动而启动。因为service的启动强依赖于该service对应的DB资源,所以service的依赖关系中都会pullup对应的数据库。
5.RAC中SCN在不同节点间传播方式
在单实例中,Oracle数据库通过SGA来管理生成的SCN,但是在RAC中复数个实例中SCN的生成需要取得同步。
在早期的RAC版本中采用Lamport SCN的方式同步SCN。
其原理为各实例中commit时更新的SCN不会立刻影响其它节点的SCN,而是会随着节点间的信息交换传到其它节点上去。受信的节点会去比较自身的SCN跟传过来的节点的SCN大小。如果比自身的SCN大,则修改自己的SCN。另外即便节点间不发生信息交换,LCK进程也会每3秒同步一次SCN。
这就带来一个问题,不同节点间SCN的同期是有延迟的。如果因为OS或者网络等原因发生的SCN同期延迟时间会更长。
所以在10.2以后采用了Broadcast on Commit的方式传播SCN。这种SCN传播方式的原理为:只有数据改变时才会传播SCN。Oracle数据库与其它数据一样也是采用REDO落盘成功方式来标记数据落盘成功。所以SCN号的传播自然就落在了LGWR进程身上。而RAC节点间信息传播则是LMS等进程,那么LGWR一旦将redo信息写入重做日志,就会将最新的SCN发送给LMS等,然后LMS等进程将最新的SCN传播给其它节点。
Broadcast on Commit与Lamport SCN的不同点则是一个是基于改变的传播方式,另一个则是基于时间的传播方式。
6. REDO 和 UNDO
RAC和单实例oracle数据库一样有REDO和UNDO。但是不同点是RAC数据库中的每个实例都有自己的REDO日志文件和UNDO表空间。