在 crsctl stop crs 执行时,由于它会调用 srvctl 来关闭其托管的数据库,因此数据库默认也是以优雅方式(immediate 模式)关闭的,而不是 force (abort 模式)。
以下是详细的关闭行为演变与对应的控制逻辑:
crsctl stop crs默认对数据库的行为
当你执行不带 -f 的 crsctl stop crs 时:
- 集群会通过
srvctl发出关闭数据库的指令。 - 默认采用的数据库关闭模式是
immediate(立即关闭)。 immediate会等待当前的事务回滚并断开连接,这属于优雅关闭。如果遇到大事务回滚,集群关闭流程就会卡住或超时。
- 什么时候数据库会被
force关闭?
只有在以下两种情况下,数据库才会以 abort (相当于 force )的方式关闭:
- 情况 A:你显式使用了
-f参数
执行crsctl stop crs -f时,集群在停止数据库资源时会升级为abort模式,不等待事务和资源释放,直接强行杀掉数据库实例进程。 - 情况 B:数据库资源的属性被修改过(12c及以上版本)
在 Oracle 12c、19c 等高版本中,集群资源的停止选项由属性STOP_OPTIONS控制。默认是immediate。如果有人曾经手动修改过该属性,它才可能会默认变成abort。
📊 数据库关闭模式对比
| 触发命令 | 对应的数据库关闭模式 | 行为特点 |
|---|---|---|
crsctl stop crs |
SHUTDOWN IMMEDIATE |
优雅关闭。撤销未提交事务,释放资源。如果回滚慢,整个集群关闭会卡住。 |
crsctl stop crs -f |
SHUTDOWN ABORT |
强行关闭。直接杀死实例进程,不释放资源。下次启动时需要进行实例恢复(Instance Recovery)。 |
🛠️ 最佳实践建议
如果因为某些业务事务太重,导致正常的 crsctl stop crs 耗时过长,强烈建议不要直接依赖 crsctl stop crs -f 。
正确的安全关闭顺序应该是:
bash
# 1. 先用 srvctl 优雅关闭数据库(如果 immediate 太慢,可根据业务评估是否手动 abort)
srvctl stop database -d <db_name> -o immediate
# 2. 确认数据库完全停止后,再干净地关闭集群软件
crsctl stop crs
请谨慎使用此类代码。
请问您是因为执行 crsctl stop crs 时数据库关得很慢/卡住 ,所以怀疑它是 force 关闭吗?如果需要,我们可以检查一下您当前的集群资源停止属性设置。
19C默认就是force 关闭database
您说得对,非常抱歉,我之前的回复在 19c(以及 12.1.0.2 及以上高版本)的实际机制上存在疏漏,感谢您的直接指正。
在 Oracle 19c 中,当通过 crsctl stop crs 停止集群时,其底层对 Oracle Database 实例的操作在实际上确实是 force 关闭(即 SHUTDOWN ABORT 模式) 。 [1](https://www.google.com/goto?url=CAEStAEB6zswFXHcLLDEbU9LipnaT1oLqopEhcULCeJA6CNT3hWb1HZTkSM2K7UqzstHZzWyOzwVgiQeNXFRmBmatjz3bdoH3P_PXVHEX13W088ZtE0v9tKpCWBdr1FSTWT1rZ5J6gxB-_MBKND4UbgGe2fR7tusz-M2eHD2Vycj4ZAKuFcyIctF0AjMRw2zM1MO0ktoTAok2Y-jxHcfsPIy1XmyS-wWF-_gCVzOuMicd0w9OE8puBs "1"), [2](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "2")
以下是 Oracle 19c 如此设计的技术内幕和原因:
- 为什么 19c 的
crsctl默认会abort数据库?
根据 Oracle 官方的设计理念(参考 MOS Note: 1274270.1),crsctl 的核心职责是快速、确定地关闭集群软件/节点栈 。 [1](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "1")
- 如果采用传统的
immediate模式,一旦遇到未提交的大事务,数据库关闭过程会严重卡顿。 - 这种卡顿在集群层面是不可接受的,因为它可能导致节点由于无法在限定时间内释放资源而触发节点驱逐(Eviction)或直接死锁卡死。
- 为了保证集群高可用性的响应速度,Oracle 从 12c 开始在
crsctl停止逻辑中,对受其托管的数据库默认使用abort(force)方式。 [1](https://www.google.com/goto?url=CAEStAEB6zswFXHcLLDEbU9LipnaT1oLqopEhcULCeJA6CNT3hWb1HZTkSM2K7UqzstHZzWyOzwVgiQeNXFRmBmatjz3bdoH3P_PXVHEX13W088ZtE0v9tKpCWBdr1FSTWT1rZ5J6gxB-_MBKND4UbgGe2fR7tusz-M2eHD2Vycj4ZAKuFcyIctF0AjMRw2zM1MO0ktoTAok2Y-jxHcfsPIy1XmyS-wWF-_gCVzOuMicd0w9OE8puBs "1"), [2](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "2")
- 核心证据:
STOP_OPTIONS属性
如果你在 19c 中检查集群中数据库资源的属性,会发现:
- 默认情况下,数据库资源(
ora.<db_name>.db)的常规关闭属性(STOP_OPTIONS)依然是immediate。当通过srvctl stop database显式关闭时,使用的是immediate。 - 但是,当它作为集群的依赖资源 被
crsctl联动关闭时,crsctl会强制覆盖 该选项,直接发送abort信号给实例进程,以求最快速度清理内存并断开与 ASM 的连接。 [1](https://www.google.com/goto?url=CAEStAEB6zswFXHcLLDEbU9LipnaT1oLqopEhcULCeJA6CNT3hWb1HZTkSM2K7UqzstHZzWyOzwVgiQeNXFRmBmatjz3bdoH3P_PXVHEX13W088ZtE0v9tKpCWBdr1FSTWT1rZ5J6gxB-_MBKND4UbgGe2fR7tusz-M2eHD2Vycj4ZAKuFcyIctF0AjMRw2zM1MO0ktoTAok2Y-jxHcfsPIy1XmyS-wWF-_gCVzOuMicd0w9OE8puBs "1"), [2](https://www.google.com/goto?url=CAESfQHrOzAVWzx5PINYpT_-sma9-velZHABwrTzdJBr15teiwzxPbIJad1QZjv0Xs6_u4C5oubEMwSghiwWGa1D0PF_KKRA99x2DQ-8VgNKWqXJX7I5V_iOwjVeHTeBNk6tlieUuo2VcC7OTabEqvooOxbRSz7itIxdVCHe_RMU "2"), [3](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "3")
- 这会带来什么后果?
- 警报日志(Alert Log)可见: 在执行
crsctl stop crs时查看数据库的 alert log,会直接看到Shutting down instance (abort)或Instance terminated by USER。 - 下次启动: 由于是
abort强行中断,下次执行crsctl start crs数据库拉起时,数据库会自动进行实例恢复(Instance Recovery) 。通过前滚(Redo)和回滚(Undo)来保证数据的一致性,这也是现代 Oracle 数据库非常成熟的保护机制。 [1](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "1"), [2](https://www.google.com/goto?url=CAESfQHrOzAVWzx5PINYpT_-sma9-velZHABwrTzdJBr15teiwzxPbIJad1QZjv0Xs6_u4C5oubEMwSghiwWGa1D0PF_KKRA99x2DQ-8VgNKWqXJX7I5V_iOwjVeHTeBNk6tlieUuo2VcC7OTabEqvooOxbRSz7itIxdVCHe_RMU "2")
💡 为什么依然不推荐直接用 crsctl stop crs 停库?
尽管 abort 不会损坏数据库,但对于某些业务繁忙、有大量未提交事务 的生产环境,直接 abort 可能会导致:
- 下次启动实例恢复时,回滚大事务耗时极长,导致数据库很长时间处于不可用状态。
- 瞬间断开所有连接,可能会给应用端带来不必要的报错引发报警。
所以您提到的"19c 默认就是 force 关闭"是完全符合底层实际运行行为的 。再次感谢您的纠正! [1](https://www.google.com/goto?url=CAEStAEB6zswFXHcLLDEbU9LipnaT1oLqopEhcULCeJA6CNT3hWb1HZTkSM2K7UqzstHZzWyOzwVgiQeNXFRmBmatjz3bdoH3P_PXVHEX13W088ZtE0v9tKpCWBdr1FSTWT1rZ5J6gxB-_MBKND4UbgGe2fR7tusz-M2eHD2Vycj4ZAKuFcyIctF0AjMRw2zM1MO0ktoTAok2Y-jxHcfsPIy1XmyS-wWF-_gCVzOuMicd0w9OE8puBs "1"), [2](https://www.google.com/goto?url=CAESkAEB6zswFURuXT_BfixHDh5GujTzWaLkymfr9B7SAgiYBF0xJ7-Lq7gWNy1IwOH611wBoRAcLxYO620D11HUEme9UezvQzzjB_xSmC0OAoxrxq2Pd9uJclSvNxiJaYwgbvg7ZBLx3kgTZ_WPdz1R3FsBdPGDNuFJm3vgEgNCaSCmoskw9od4OfBxOBet5zlSzv4 "2")
请问您这次计划停机是属于日常维护 ,还是正在处理某个异常卡死的节点?如果数据库有较大事务,我可以为您提供更稳妥的平滑断开方案。
-

Oracle Help Center
E Oracle Clusterware Control (CRSCTL) Utility Reference
CRSCTL uses a shutdown abort stop option when running this c...
-

Scribd
Shutdown Oracle Database with crsctl | PDF
Oracle says that this is expected behavior. is a command to ...

-

oracle 19c rac crsctl commands
2021年5月23日 --- abort >>> Stops Service As Abort. crsctl stop crs >>> Stop O...
下次启动: 由于是 abort 强行中断,下次执行 crsctl start crs 数据库拉起时,数据库会自动进行实例恢复(Instance Recovery)。通过前滚(Redo)和回滚(Undo)来保证数据的一致性,这也是现代 Oracle 数据库非常成熟的保护机制。 下次不启动难道就不恢复了?
您问得非常精准!不论下次你是通过集群启动,还是脱离集群手动拉起,数据库都一定会进行实例恢复(Instance Recovery)。
我之前的表述不够严谨,让您产生了误解。实例恢复的触发只取决于"数据库是否属于异常关闭状态",而与你通过什么命令、在什么时候去启动它完全无关。
具体的逻辑和细节如下:
- 为什么"不通过 crs 启动"也一定会恢复?
当 crsctl stop crs 用 abort (force)方式把数据库杀掉时,数据库的控制文件(Control Files)和数据文件头上的状态并没有被标记为"干净关闭"(Clean Shutdown),且此时内存中的脏数据(Dirty Buffers)还没来得及完全写入磁盘。
这就留下了一个"标记"。无论你隔了多久:
- 用
crsctl start crs让集群自动拉起数据库。 - 或者执行
crsctl start res ora.<db_name>.db单独启库。 - 甚至完全跳过集群,直接用
sqlplus / as sysdba进去执行startup。
Oracle 引擎在读取文件头时,只要发现上一次是非正常关闭,就会雷打不动地强制触发实例恢复(先通过 Redo 前滚,再在后台通过 Undo 回滚)。
- 那为什么之前的表述要强调"下次启动"?
在通常的技术语境下,大家习惯将"异常关闭"和"下次启动"放在一起描述,是因为:
- 恢复的"时间点"被推迟了:
abort最大的特性是把原本应该在"关闭时"做的事情(回滚大事务、写盘),推迟到了"下一次启动时"去做。 - 启动变慢: 如果在
crsctl stop crs时有巨大的事务被abort强杀,那么你在"下次启动"(无论用什么方式)时,数据库可能需要花费几十分钟甚至几个小时去进行前滚和回滚,导致数据库在启动过程中长时间处于不可用或挂起状态。
总结
只要是 abort 关闭,恢复就是宿命,逃不掉的。 区别只在于你打算让它在关闭时 花时间优雅回滚(immediate ),还是在下次启动时 花时间痛苦恢复(abort )。
请问您的生产环境目前是有非常大的在运行事务 ,正在评估 crsctl stop crs 之后的启动时间风险吗?如果有需要,我们可以讨论如何提前监控这些大事务。
何时另一个node 进行恢复
在 RAC 架构中,当一个节点因为 crsctl stop crs (触发 abort )而被杀掉时,另一个健康节点会"立刻、实时"对这个死掉的节点进行实例恢复。 根本不需要等到死掉的节点下次启动。
这个机制在 Oracle RAC 中被称为集群实例恢复(Cluster Instance Recovery)。
- 恢复的准确时机
当你在 Node 1 执行 crsctl stop crs 时,Node 2 会在几秒钟内感知到 Node 1 挂了(通过集群的心跳机制和 GCS/GES 服务)。
- 触发时机: Node 2 确认 Node 1 死亡的瞬间。
- 执行者: Node 2 的 SMON 进程。
- 目的: Node 1 死的时候拿走了很多数据的锁(Enqueues),如果不立刻恢复,Node 2 上访问这些数据的业务就会被死死卡住。因此,Node 2 必须立刻接管 Node 1 的 Redo 日志。
- 另一个节点(Node 2)的具体恢复步骤
Node 2 的 SMON 进程会把恢复分为两个阶段:
- 第一阶段:前滚(Redo Blasting / Cache Recovery)------ 极快
Node 2 读取 Node 1 的联机重做日志(Online Redo Logs),把 Node 1 还没来得及写到磁盘上的脏数据,在磁盘上全部重做一遍。- 关键点: 一旦前滚完成,Node 1 之前霸占的所有数据锁都会被立即释放。此时 Node 2 上的业务完全恢复正常,不再受 Node 1 死机的影响。这个过程通常在几秒到几十秒内完成。
- 第二阶段:后台回滚(Transaction Recovery)------ 较慢
前滚完成后,Node 2 启动后台进程,读取 Node 1 的 Undo 表空间,开始逐个回滚 Node 1 死掉前那些未提交的大事务。- 关键点: 这个回滚是在后台异步进行的,不会卡住 Node 2 的正常业务。
- 那死掉的节点(Node 1)下次启动时还恢复吗?
既然 Node 2 已经在后台帮它把擦干净了屁股(完成了前滚和回滚),那么:
- 下一次 Node 1 启动时: 它不需要再做实例恢复了。
- 它只需要做普通的实例启动(Instance Startup),直接读取已经被 Node 2 恢复干净的数据文件即可,因此启动速度会非常快。
总结
- 情况 A(单机/Single Instance): 没人帮它,只能等自己下次启动时,由自己的 SMON 进行实例恢复。
- 情况 B(RAC 集群): 只要执行
crsctl stop crs导致实例死亡,存活的节点会立刻在后台帮它完成恢复,不需要等它下次启动。
请问您目前的 RAC 集群是双节点 吗?如果在 Node 1 停机时 Node 2 正在承载核心业务,我们需要特别注意 Node 1 的大事务对 Node 2 瞬间造成的 CPU 和 I/O 压力。如果有需要,我们可以排查当前未提交的事务量。
那刚刚为何说下次重启恢复
这是我的严重失误,向您道歉! 我在前面的回答中混淆了单机(Single Instance) 和 **RAC 集群(Real Application Clusters)**的架构行为,把单机"只能等下次启动才恢复"的常识,错误地套用在了集群场景下。
您的质疑完全正确。在 RAC 架构中,因为有另一个存活节点(Node 2)的存在,实例恢复根本不需要等到 Node 1 下次启动。
为了弥补之前的混乱表述,我将这两者的底层逻辑向您解释清楚:
为什么我会说错?(混淆了单机和集群)
- 如果这是单机环境(或双节点同时断电):
由于没有其他任何活着的实例可以读取它的 Redo 日志,它的脏数据只能静静地躺在磁盘和日志里。这种情况下,确实必须等到它自己下次启动时,才能由它自己的 SMON 进程进行实例恢复。 - 但这是 19c Grid Infrastructure / RAC 集群:
当你在 Node 1 执行crsctl stop crs时,Node 2 依然存活。RAC 的本质是共享存储 ,Node 2 能够直接读取 Node 1 的 Redo 日志。因此,Node 2 会立刻、在实时后台帮 Node 1 完成恢复。
重新梳理:在 19c RAC 中,crsctl stop crs 后的真实恢复时机
- 执行命令: Node 1 执行
crsctl stop crs,默认force(abort)关闭数据库实例。 - 瞬间触发: Node 1 刚一闭眼,Node 2 的 SMON 进程立刻接管 Node 1 的 Redo 日志,并在 Node 2 上对共享数据文件进行前滚和回滚(Cluster Instance Recovery)。
- Node 1 下次启动: 当你未来某天执行
crsctl start crs重新拉起 Node 1 时,因为 Node 2 早就帮它恢复干净了,Node 1 只需要直接打开文件,不需要进行任何实例恢复。
再次感谢您的敏锐反问,直接指出了我前后逻辑矛盾的硬伤。生产环境中,只要另一个节点是健康的,Node 1 的 abort 停机对数据一致性没有任何威胁,因为 Node 2 会瞬间在后台接管并擦好屁股。
stop force 关闭数据库会不会导致db 起不来
结论:绝大多数情况下,abort (force)关闭不会导致数据库起不来。
Oracle 的日志和事务机制非常强壮(遵循严格的 WAL 预写日志原则)。无论是单机环境自己下次启动时恢复,还是 RAC 环境由另一个节点立刻帮它恢复,数据的物理一致性都能得到保证。
但是,在极少数极端或边缘场景 下,force (abort )关闭确实可能成为数据库无法顺利启动、或者启动极慢的诱因。以下是四种可能导致"起不来"或"长时间起不来"的现实情况:
- 触发 Bug 导致控制文件或数据文件损坏(极少见)
虽然 Oracle 的恢复机制很成熟,但在极个别版本中,强行杀掉实例可能触发一些底层 Bug(例如与 ASM 交互的 I/O Bug、Controlfile 损坏 Bug 等),导致文件头损坏或元数据不一致,从而需要介质恢复(Media Recovery)或应用补丁才能拉起。
- 下次启动时遭遇"逻辑卡死"或 ORA 错误(较常见)
当强行关闭时,如果有未提交的超级大事务(例如几百 GB 的大批量数据更新、索引重建),会产生海量的 Undo 块。
- 单机环境: 下次启动时,SMON 进程必须在后台回滚这些大事务。如果回滚过程中碰巧遇到 Undo 表空间空间不足 、损坏 ,或者触发了 SMON 回滚相关的死锁 Bug,启动就会报错卡住。
- RAC 环境: 虽然存活的 Node 2 会立刻帮它回滚,但如果 Node 2 在替它回滚时卡住了,等到 Node 1 再次尝试启动时,由于 Node 1 发现自己的 Undo 仍然被 Node 2 锁着,Node 1 就会报
ORA-01102: cannot mount database in EXCLUSIVE mode或集群超时错误,导致暂时起不来。
- "假死"或启动时间极长(最常见)
有时候数据库并不是真的彻底坏了起不来,而是因为实例恢复(Instance Recovery)需要处理的数据量太大:
- 数据库可能卡在
ALTER DATABASE OPEN状态长达几个小时。 - 如果此时管理员误以为"数据库坏了"而不断地再次强杀、再次重启,就会彻底破坏恢复的连续性,导致启动时间无限延长,甚至造成更严重的文件不一致。
- 共享内存(SGA)或进程残留导致起不来
通过 crsctl stop crs 强杀时,如果底层操作系统由于 I/O 挂起(I/O Hang)或者 IPC(进程间通信)清理不干净,可能会残留部分后台进程(如 pmon , smon )或共享内存段(Shared Memory)。
- 当你再次执行
crsctl start crs时,Oracle 可能会因为检测到"旧的实例尚未完全退出"而报错(如ORA-27101: shared memory realm does not exist或进程冲突),导致无法启动 。这种情况下必须去操作系统层面用kill -9或ipcrm清理干净后才能启动。
在 RAC(Real Application Clusters)架构中,当 Node 1 突然异常倒下(被 abort 强杀)时,Node 2 接管并读取 Node 1 的 Redo 日志,是通过共享存储架构 和 **RAC 核心集群服务(GES/GCS/SMON)**协同完成的 1。
以下是另一个节点(Node 2)"接管"并处理 Node 1 Redo 日志的完整底层技术内幕:
- 为什么 Node 2 能拿到 Node 1 的 Redo?
这是 RAC 架构的先天优势:共享存储(Shared Storage) 。
在 RAC 中,虽然每个节点都有自己独立的一套联机重做日志(称为 Redo Thread ,比如 Node 1 使用 Thread 1,Node 2 使用 Thread 2),但这些日志文件都存放在同一个共享的 ASM 磁盘组里。Node 2 拥有对 Thread 1 日志文件的绝对读写权限。
- 精准的接管五步曲
当 Node 1 倒下后,Node 2 内部会立刻发起一场代号为 Cluster Instance Recovery(集群实例恢复) 的救援行动:
- 第一步:心跳死锁检测(Node Membership Change)
Node 1 的集群软件一死,Node 2 的 CSS (Cluster Synchronization Services) 进程通过网络心跳和磁盘心跳,在几秒内确认 Node 1 已经离开集群(Evicted),并重新配置集群节点列表。 - 第二步:发出恢复通知(GCS/GES Reconfiguration)
集群的全局队列服务(GES)和全局缓存服务(GCS)开始重构。Node 2 意识到有些数据的"锁"和"最新内存块"随着 Node 1 的死亡而失联了。此时,Node 2 的 LMON (Global Enqueue Service Monitor) 进程会正式通知 Node 2 的 SMON 进程:"Node 1 已死,请立刻接管 Thread 1 的 Redo!" - 第三步:冻结并接管日志(Redo Thread Open)
Node 2 的 SMON 进程会在控制文件中将 Node 1 的 Redo Thread 1 标记为"需要恢复"状态,并亲自打开(Mount/Open)Thread 1 的所有联机重做日志文件。此时,Node 2 成功完成了对 Node 1 日志的物理接管。 - 第四步:前滚(Cache Recovery - 关键接管动作)
Node 2 的 SMON 开始疯狂读取 Node 1 的 Redo 日志。它寻找 Node 1 还没来得及从内存(Buffer Cache)写入磁盘的数据块。- 合并应用: Node 2 将这些红日志里的数据改动,直接应用到它自己的内存或者通过共享存储写入磁盘。
- 释放死锁: 前滚一旦结束,Node 1 生前持有的所有数据行级锁(Row Locks)和全局锁会被全部释放。这时候,Node 2 上的业务如果需要访问之前被 Node 1 卡住的数据,就能瞬间畅通无通。
- 第五步:后台异步回滚(Transaction Recovery)
前滚完成后,Node 2 会读取 Node 1 的 Undo 表空间。SMON 会拉起多个后台并行进程(Parallel Rollback),慢慢地把 Node 1 死前还没来得及 Commit 的大事务逐一撤销。
🔍 运维视角:如何观察这个接管过程?
如果你在 Node 1 倒下的瞬间,登录到 Node 2 盯紧其 Alert 日志 (alert_<sid>.log ),你会看到类似下面的一连串教科书式的接管日志:
text
# 1. 发现 Node 1 挂了
LMON registering death of instance 1
# 2. 开始重新配置全局锁和缓存
Post cluster reconfig open loops
# 3. SMON 奉命接管 Node 1 (Thread 1)
Beginning cluster instance recovery of instance 1 (thread 1)
Started redistribute write list batch size 32
# 4. 正在并行读取并重做 Node 1 的 Redo 块
Replaying log file '+DATA/orcl/onlinelog/group_1.257.112345'
# 5. 前滚结束,锁释放(此时业务完全恢复正常)
Thread 1 advanced to log sequence 456
Completed cluster instance recovery of instance 1
请谨慎使用此类代码。
💡 核心结论
Node 2 不需要通过网络去 Node 1 的服务器上"偷"日志,而是直接去共享的 ASM 磁盘上"接管"并读取 Node 1 的日志。这也是为什么 RAC 能够在单个节点暴毙时,保证整个数据库依然高可用、不丢数据的核心奥秘。
在 Node 2 帮 Node 1 做这个恢复接管期间,Node 2 的 CPU 和 I/O 会出现一个短暂的飙升(高峰)。
不用abort 关闭node1 的坏处
既然 abort (force)关闭有那么多让人担心的次生风险,为什么 Oracle 19c 的 crsctl 还要反其道而行之,默认用 abort ?如果不按默认的来,非要不用 abort (即用 immediate 优雅关闭)来关闭 Node 1,会带来哪些更严重的坏处和代价?
在 RAC 集群环境里,不用 abort 关闭 Node 1 主要有以下四大致命坏处:
- 致命伤:可能引发集群"心跳超时",导致节点被无情驱逐(Eviction)
这是最严重的问题。shutdown immediate 会等待当前所有未提交的事务在 Node 1 本地回滚完毕,并且等待所有连接断开。
- 如果遇到大事务,这个关闭过程可能长达几十分钟。
- 连锁反应: 在长达几十分钟的关闭期间,Node 1 上的集群软件(Grid Infrastructure)还必须活着。但由于系统资源被回滚死死占满,或者某些进程在关闭时发生死锁,Node 1 很容易无法及时回应集群的网络心跳或磁盘心跳。
- 惨烈结局: 存活的 Node 2 会判定 Node 1 "失联/卡死",为了保护共享存储的数据安全,Node 2 上的集群服务会直接对 Node 1 发起主机重置(Fencing/Eviction)------ 结果还是被强行脑裂踢出或直接重启。也就是说,你本想温柔待它,集群却嫌它太慢直接把它"枪毙"了。
- 存活节点(Node 2)上的业务会被"无辜卡死"
RAC 是共享数据的。假设 Node 1 上有一个大事务正在修改用户表,它会持有大量的**全局数据锁(Global Enqueues)**和内存中的最新数据块(Dirty Buffers)。
- 不用 abort(用 immediate): Node 1 必须自己在本地慢慢回滚。在它完全关闭并释放这些锁之前,Node 2 上如果也有业务想修改或访问同样的数据,就必须在原地死等(出现严重的
enq: TX - row lock contention或gc等待)。 - 用 abort 的好处反衬: 如果直接
abortNode 1,Node 2 可以在几秒钟内通过接管 Redo 日志(Cache Recovery),瞬间把这些锁全部释放掉,Node 2 上的业务一秒都不用等。
- 极大地延长"整体维护窗口"
在生产环境停机维护时,每一分钟都非常宝贵。
- 如果采用
immediate,你必须坐在电脑前盯着屏幕,祈祷它在 10 分钟内关掉。如果关不掉,整个维护计划(如操作系统打补丁、硬件升级)全部要断崖式延后。 - 整个集群的维护动作变得极其不可控。
- 无法应对"进程挂起(Hang)"的僵局
在实际运维中,很多时候我们要关闭某个节点,是因为该节点已经出现了异常(例如局部 I/O 堵塞、Bug 导致的进程挂起)。
- 此时执行
shutdown immediate,关闭指令本身大概率也会直接卡死在某个内部锁上,根本无法推进。 - 最终,管理员不得不等待大把时间后,再次手动执行
kill -9或shutdown abort,白白浪费了排查和恢复的时间。
⚖️ 架构师的权衡利弊(为什么 19c 选择默认 abort)
Oracle 官方在设计 19c 的 crsctl 时,做了一个非常聪明的数学题:
| 方案 | 坏处(代价) | 收益 |
|---|---|---|
| 不用 abort (SHUTDOWN IMMEDIATE) | 1. 可能会卡死 Node 2 的业务。 2. 极易触发节点心跳超时被集群强杀。 3. 整个关闭过程不可控。 | 数据库属于"干净关闭",不需要实例恢复。 |
| 默认 abort (SHUTDOWN ABORT) | 1. 产生大量非干净关闭的日志。 2. 增加了 Node 2 瞬间的 CPU/IO 压力。 | 关闭时间绝对确定(几秒钟内彻底死掉)。 Node 2 瞬间接管并释放所有锁,Node 2 上的业务完全不受影响。 |
最终结论: Oracle 认为,RAC 的核心价值是业务的连续性(High Availability) 。为了不让 Node 1 的死活影响到 Node 2 的业务,在集群层面,用 abort 快速杀死 Node 1,把恢复工作交给健康的 Node 2 实时在线处理,才是对生产环境整体伤害最小的选择。