特殊恢复:ORA-00704、ORA-00604、ORA-01555故障的说明


在上一篇文章中特殊恢复:ORA-00704、ORA-00604、ORA-01555故障时快速定位触发报错的数据块,我们介绍了数据库在启动时遇到 ORA-00704、ORA-00604、ORA-01555 报错时,如何通过 Trace 文件定位触发报错的 SQL 的执行计划、等待事件及访问的数据块。本篇将继续上文内容,详细讲解在数据库启动过程中遇到这些报错时,如何分析、定位原因并解决问题。

报错信息如下:

www.htz.pw > alter database open resetlogs;
alter database open resetlogs
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00604: error occurred at recursive SQL level 1
ORA-01555: snapshot too old: rollback segment number 6 with name "_SYSSMU6_3654194381$" too small
Process ID: 9202
Session ID: 1 Serial number: 3

面对这四个 ORA 报错,如何判断哪个才是根本原因?有一个分析规则:从最后一个报错往前看。这里,ORA-01555 是导致整个报错链的根本原因,其它 ORA 错误都是由 ORA-01555 引发的。ORA-01555 的含义是:数据库在启动初始化过程中,因回滚段过小,导致 SQL 执行失败,进而引发数据库异常关闭。因此,分析时应首先聚焦于 ORA-01555 的成因。

下面简单回顾一下 ORA-01555 报错的原理。

ORA-01555 是“快照过旧”导致的错误。可以理解为:SQL 执行时需要访问历史版本的数据,这时需要利用 UNDO 回滚数据块,但在 UNDO 段中找不到所需的回滚信息,于是触发报错。

Oracle 利用 UNDO 记录回滚有两种机制:

  • 大对象段
    大对象段通过数据块内的历史镜像实现回滚,类似于 PostgreSQL 的回滚机制。
  • 非大对象段
    非大对象段通过 UNDO 段实现回滚。在 Oracle 中,UNDO 段分为系统表空间中的 UNDO 段和 UNDO 表空间中的 UNDO 段。因此,系统表空间中的系统对象回滚会用系统 UNDO 段,普通用户对象则用 UNDO 表空间的 UNDO 段。

导致回滚信息无法找到的常见原因有:

  • UNDO 段头的 SCN 值异常,导致根据数据块 XID 找到的 UNDO 段不满足要求;
  • UNDO 条目不存在,在 UNDO 段中找不到对应条目信息;
  • UNDO 段本身不存在;
  • UNDO 段存在坏块。

不过,UNDO 回滚记录找不到,并不一定都会触发 ORA-01555 报错。

本篇重点分析数据库启动过程中出现 ORA-01555 报错的场景。通常,这类报错是因为系统对象所在的数据块需要回滚,但在 SYSTEM 的 UNDO 段中找不到回滚记录所致。

那么,哪些情况下会触发这种报错?

  • SQL 执行时遇到未提交的事务,需要回滚事务时会用到 UNDO 信息;
  • SQL 执行时需要读取前镜像数据,需要回滚数据块时也会用到 UNDO 信息。

针对上述两种情况,解决方案也有所不同。

在下篇文章中,我会详细介绍如何解决这些问题,敬请期待。

------------------作者介绍-----------------------

姓名:黄廷忠

现就职:Oracle中国高级服务团队

曾就职:OceanBase、云和恩墨、东方龙马等