找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1132

积分

0

好友

164

主题
发表于 昨天 22:45 | 查看: 1| 回复: 0

图片

适用范围

  • Version >= 11g
  • Platform:Linux

问题概述

bootstrap$ 在Oracle数据库中的作用类似于操作系统的引导区,其中包含了数十张关键的基表。其中任何一张基表的数据被删除(执行了deletecommit,随后数据库重启),都可能导致数据库实例启动时抛出ORA-00600ORA-00704错误而失败。

由于数据库无法启动,闪回等常规恢复操作也无法实施。此时,恢复思路主要有两种:

  1. 设法恢复被删除的基表数据。
  2. 使用ODU(Oracle Database Unloader)等工具直接从数据块中抽取业务数据,然后重新建库并导入。

方案对比

  • 恢复基表数据:优点是恢复速度相对较快,成功后数据库能直接OPEN,无需进行数据导出、重建库和导入的复杂流程。缺点是如果故障场景过于复杂,恢复后仍可能遇到其他问题。
  • 使用ODU抽取数据:优点是即使数据库完全无法打开,也能最大概率地挽救业务数据。缺点是技术门槛高,恢复周期长。

那么,当数据库无法启动时,我们如何判断是否由bootstrap$基表损坏引起?又该选择哪种恢复方案呢?一个通用的策略是:优先尝试使用工具恢复基表数据;如果能成功恢复并使数据库正常打开,则无需动用ODU。ODU应作为保障数据安全的最后手段。

以下将通过一个模拟tab$基表数据被删除的场景,演示问题的诊断与恢复全过程。

问题现象与诊断

  1. 模拟故障
    首先查询并备份tab$表,然后删除其数据并提交。
-- 查询当前tab$中的数据量
27-OCT-25> select count(*) from tab$;
  COUNT(*)
----------
      1321

-- 备份基表
27-OCT-25> create table tab$_bak as select * from tab$;
Table created.

-- 删除数据并提交
28-OCT-25> delete from tab$;
1321 rows deleted.
28-OCT-25> commit;
Commit complete.
  1. 重现故障
    重启数据库,观察错误信息。
28-OCT-25> shutdown abort;
ORACLE instance shut down.
28-OCT-25> startup
ORACLE instance started.
Total System Global Area  521936896 bytes
Fixed Size                  2254824 bytes
Variable Size             377489432 bytes
Database Buffers          134217728 bytes
Redo Buffers                7974912 bytes
Database mounted.
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00600: internal error code, arguments: [16703], [1403], [20], [], [], [], [], [], [], [], [], []

同时,在Alert日志中也会记录ORA-00704: bootstrap process failure错误。

诊断关键点:如果在数据库OPEN阶段出现ORA-00704: bootstrap process failure报错,基本可以确定是bootstrap$中的基表数据出现了问题。错误参数[16703], [1403], [20]提供了进一步的线索。

  1. 深度追踪
    通过10046事件跟踪数据库启动过程,精确定位问题SQL。
28-OCT-25> startup mount;
ORACLE instance started.
...
Database mounted.

28-OCT-25> oradebug setmypid
Statement processed.
28-OCT-25> oradebug event 10046 trace name context forever, level 4
Statement processed.
28-OCT-25> alter database open;
alter database open
*
ERROR at line 1:
ORA-01092: ORACLE instance terminated. Disconnection forced
ORA-00704: bootstrap process failure
ORA-00704: bootstrap process failure
ORA-00600: internal error code, arguments: [16703], [1403], [20], [], [], [], [], [], [], [], [], []

查看生成的跟踪文件(prod_ora_70891.trc),可以发现关键信息:

PARSING IN CURSOR #...
select rowcnt,blkcnt,empcnt,avgspc,chncnt,avgrln,nvl(degree,1), nvl(instances,1) from tab$ where obj# = :1
...
BIND #0: ... value=20
...
FETCH #...: ... r=0 ...

跟踪日志显示,数据库在OPEN时尝试执行一条查询tab$表的SQL,传入的绑定变量obj#=20,并且没有获取到任何数据(r=0)。这正好对应了错误参数[20][1403]ORA-01403: no data found)。因此可以确定,故障原因是obj#=20的记录在tab$表中被删除,导致引导进程失败。

恢复实战:使用工具恢复基表数据

本次恢复采用一款专用工具,其原理是扫描基表对应的数据块,利用BBED工具清除数据块上的“删除标记”。由于被删除的数据实际上仍物理存在于数据块中,清除删除标记即等效于恢复了数据。这里需要区分聚簇表和非聚簇表,因为它们在BBED中的存储格式不同。

  1. 获取恢复所需的关键参数
    在一个同平台、同版本的正常数据库中执行以下查询,收集必要信息。
-- 1. 确认TAB$是否为聚簇表,并获取聚簇名
select cluster_name,table_name from dba_tables where table_name='TAB$';
CLUSTER_NAME           TABLE_NAME
------------------------------ ------------------------------
C_OBJ#                 TAB$  -- TAB$是聚簇表,属于C_OBJ#聚簇

-- 2. 获取聚簇的dataobj# (kdbt参数,-k)
select obj#,dataobj# from obj$ where name = 'C_OBJ#';
      OBJ#   DATAOBJ#
---------- ----------
         2          2

-- 3. 获取TAB$表的数据段头块位置 (blkloc_segment_header参数,-n)
select t1.obj#,t1.name,t2.ts#,t2.file#,t2.block#,t2.tab#
  from obj$ t1,tab$ t2
 where t1.obj# = t2.obj#
   and t1.NAME='TAB$'
   and t2.DATAOBJ#=2;
      OBJ# NAME             TS#      FILE#     BLOCK#       TAB#
---------- ---------- ---------- ---------- ---------- ----------
         4 TAB$                 0          1        144          1
-- 得到第一个-n参数:144

-- 4. 获取TAB$表相关索引的信息
select index_name from dba_indexes where table_name = 'TAB$';
INDEX_NAME
------------------------------
I_TAB1

-- 5. 获取索引I_TAB1在bootstrap$中的块位置(用于设置/清除索引删除标记,-n)
select distinct dbms_rowid.rowid_object(rowid) object_id,
                dbms_rowid.rowid_relative_fno(rowid) file_id,
                dbms_rowid.rowid_block_number(rowid) block_id
  from bootstrap$
 where obj# in (select obj# from obj$ where name in ('I_TAB1'));
 OBJECT_ID    FILE_ID   BLOCK_ID
---------- ---------- ----------
        59          1        523
-- 得到第二个-n参数:523

-- 6. 获取索引I_TAB1的数据段头块位置(用于恢复索引数据块,-n)
select segment_name,header_file,header_block
  from dba_segments
 where segment_name in ('I_TAB1')
 order by 1;
SEGMENT_NAME         HEADER_FILE HEADER_BLOCK
-------------------- ----------- ------------
I_TAB1                          1          312
-- 得到第三个-n参数:312
  1. 准备数据文件列表
    创建system.cnf文件,列出SYSTEM表空间的数据文件。
-- 查询SYSTEM表空间的数据文件
set lines 120
col name for a100
select file#,name from v$datafile where ts#=0;
-- 输出示例:
-- FILE# NAME
-- ------ --------------------------------------------------
-- 1     /u01/app/oracle/oradata/prod/system01.dbf

-- 创建system.cnf文件
vi system.cnf
# 内容为:文件号 绝对路径
1 /u01/app/oracle/oradata/prod/system01.dbf
  1. 执行恢复步骤
    按照工具的使用逻辑,依次执行以下步骤。工具脚本recovery_basetab.sh的用法概要如下:
    • -n: 要处理的起始块号(段头块)
    • -k: 聚簇表的kdbt序号,非聚簇表无需此参数
    • -s: 数据库块大小(通常为8192)
    • -i: 索引名称
    • -d: 对索引操作,1为添加删除标记,0为清除删除标记
    • -t: 恢复数据类型,1为数据,2为索引
# 1. 清理可能存在的临时文件
rm -f idx_kdbr.loc

# 2. 为TAB$表的索引(I_TAB1)添加删除标记(模拟索引失效状态)
./recovery_basetab.sh -n 523 -s 8192 -i i_tab1 -d 1

# 3. 恢复TAB$表的数据块(聚簇表,需指定-k参数)
./recovery_basetab.sh -n 144 -k 1 -s 8192 -t 1

# 4. 恢复TAB$表的索引块(I_TAB1)
./recovery_basetab.sh -n 312 -s 8192 -t 2

# 5. 清除TAB$表索引(I_TAB1)上的删除标记
./recovery_basetab.sh -n 523 -s 8192 -i i_tab1 -d 0
  1. 验证恢复结果
    完成上述步骤后,尝试重启数据库。
[oracle@test 基表恢复]$ sqlplus / as sysdba
SQL*Plus: Release 11.2.0.4.0 Production on Tue Oct 28 10:20:22 2025
Connected to an idle instance.

28-OCT-25> startup
ORACLE instance started.
Total System Global Area  521936896 bytes
Fixed Size                  2254824 bytes
Variable Size             377489432 bytes
Database Buffers          134217728 bytes
Redo Buffers                7974912 bytes
Database mounted.
Database opened.  -- 数据库成功打开

28-OCT-25> select count(*) from tab$;
  COUNT(*)
----------
      1321  -- 数据已恢复

同时检查Alert日志,确认无相关错误,数据库完成正常启动和恢复过程。

总结

本文通过一个完整的实验,演示了因bootstrap$基表(以tab$为例)数据被删除导致数据库无法启动的故障现象、诊断方法及恢复流程。关键点在于通过错误信息ORA-00704和跟踪文件定位到具体受损对象,然后利用底层数据块编辑技术,按照“处理索引标记 -> 恢复数据块 -> 恢复索引块 -> 清除索引标记”的顺序进行修复。掌握此方法,可以在类似严重数据库故障发生时,为快速恢复服务提供一种有效途径。对于更复杂的损坏或此方法失效的情况,则需考虑使用ODU进行最终的数据抽取。在执行任何底层恢复操作前,务必对物理文件进行完整备份。




上一篇:OpenAI模型网络安全能力预警:从漏洞防御到攻击潜力的双刃剑效应
下一篇:MySQL外键约束FOREIGN KEY详解:数据一致性保障与实战案例
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2025-12-17 16:01 , Processed in 0.104946 second(s), 40 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2025 云栈社区.

快速回复 返回顶部 返回列表