今天在复习盖总的《深入解析Oracle》一书时,看到了介绍bootstrap$。
说实话,把以前的书再拿来复习,真的可以温故而知新。记得这本书还是上大学时看过的,一晃四年过去了。书上笔记还是犹如昨天的感觉。
先看看bootstrap$是什么,以下是在10g版本中:
SQL> select segment_type,segment_name from dba_segments where segment_name='BOOTSTRAP$';
SEGMENT_TYPE SEGMENT_NAME
------------------ --------------------
TABLE BOOTSTRAP$
SQL>
SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE,EXTENT_ID,BLOCK_ID,FILE_ID,BLOCKS FROM DBA_EXTENTS WHERE SEGMENT_NAME='BOOTSTRAP$';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCK_ID FILE_ID BLOCKS
-------------------- ------------------ ---------- ---------- ---------- ----------
BOOTSTRAP$ TABLE 0 377 1 8
SQL>
BOOTSTRAP$是一个表,位于1号文件的377块开始的8个块中。(这里是10g,11g是位于520块开始)。
数据库的启动过程主要依靠这个表里的数据:
SQL> select count(*) from BOOTSTRAP$;
COUNT(*)
----------
57
SQL>
在11g中,这个表有60条数据。
可将数据库启动在mount模式,然后启用sql_trace跟踪,启用之后就alter database open打开数据库。生成的trc文件主要描述了数据库从bootstrap$加载到 BOOTSTRAP$表里其他对象的加载。
这个表的数据只作用在数据库启动阶段,数据库open完成之后,这个表的数据就没有作用了。
但是不能对这表作任何dml操作,如果删除了记录或者表,数据库无论有多么先进的备份,都必须丢失数据才能打开数据库了。
也不一定丢失,至少必须以不完全恢复方式打开数据库。
SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE,EXTENT_ID,BLOCK_ID,FILE_ID,BLOCKS FROM DBA_EXTENTS WHERE SEGMENT_NAME='BOOTSTRAP$';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCK_ID FILE_ID BLOCKS
-------------------- ------------------ ---------- ---------- ---------- ----------
BOOTSTRAP$ TABLE 0 377 1 8
SQL> drop table bootstrap$;
drop table bootstrap$
*
第 1 行出现错误:
ORA-00701: 无法改变热启动数据库所需的对象
SQL> alter table bootstrap$ move;
alter table bootstrap$ move
*
第 1 行出现错误:
ORA-00701: 无法改变热启动数据库所需的对象
SQL> rename bootstrap$ to bootstrap$_bak;
rename bootstrap$ to bootstrap$_bak
*
第 1 行出现错误:
ORA-00701: 无法改变热启动数据库所需的对象
SQL> truncate table bootstrap$;
truncate table bootstrap$
*
第 1 行出现错误:
ORA-00701: 无法改变热启动数据库所需的对象
SQL> delete from bootstrap$;
已删除57行。
SQL> rollback;
回退已完成。
SQL>
很明显,对bootstrap$表不能做ddl操作。但是可以做dml操作。
SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE,EXTENT_ID,BLOCK_ID,FILE_ID,BLOCKS FROM DBA_EXTENTS WHERE SEGMENT_NAME='BOOTSTRAP$';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCK_ID FILE_ID BLOCKS
-------------------- ------------------ ---------- ---------- ---------- ----------
BOOTSTRAP$ TABLE 0 377 1 8
SQL> create table bootstrap$_bak as select * from bootstrap$;
表已创建。
SQL> delete from bootstrap$;
已删除57行。
SQL> commit;
提交完成。
SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE,EXTENT_ID,BLOCK_ID,FILE_ID,BLOCKS FROM DBA_EXTENTS WHERE SEGMENT_NAME='BOOTSTRAP$';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCK_ID FILE_ID BLOCKS
-------------------- ------------------ ---------- ---------- ---------- ----------
BOOTSTRAP$ TABLE 0 377 1 8
SQL> insert into bootstrap$ select * from bootstrap$_bak;
已创建57行。
SQL> commit;
提交完成。
SQL> SELECT SEGMENT_NAME,SEGMENT_TYPE,EXTENT_ID,BLOCK_ID,FILE_ID,BLOCKS FROM DBA_EXTENTS WHERE SEGMENT_NAME='BOOTSTRAP$';
SEGMENT_NAME SEGMENT_TYPE EXTENT_ID BLOCK_ID FILE_ID BLOCKS
-------------------- ------------------ ---------- ---------- ---------- ----------
BOOTSTRAP$ TABLE 0 377 1 8
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup;
ORACLE 例程已经启动。
Total System Global Area 612368384 bytes
Fixed Size 1250428 bytes
Variable Size 276827012 bytes
Database Buffers 327155712 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
数据库已经打开。
SQL>
删除表数据之后,数据库肯定无法启动:
SQL> delete from bootstrap$;
已删除57行。
SQL> commit;
提交完成。
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。
SQL> startup;
ORACLE 例程已经启动。
Total System Global Area 612368384 bytes
Fixed Size 1250428 bytes
Variable Size 276827012 bytes
Database Buffers 327155712 bytes
Redo Buffers 7135232 bytes
数据库装载完毕。
ORA-03113: 通信通道的文件结束
SQL>
看看alert日志:
ALTER DATABASE OPEN
Mon Oct 05 20:41:31 2015
Thread 1 opened at log sequence 12
Current log# 2 seq# 12 mem# 0: E:\ORADATA\DENVER\REDO02.RDO
Successful open of redo thread 1
Mon Oct 05 20:41:31 2015
MTTR advisory is disabled because FAST_START_MTTR_TARGET is not set
Mon Oct 05 20:41:31 2015
SMON: enabling cache recovery
Mon Oct 05 20:41:31 2015
Errors in file c:\oracle\product\10.2.0\admin\denver\udump\denver_ora_1780.trc:
ORA-07445: 出现异常错误: 核心转储 [ACCESS_VIOLATION] [_lmebucp+41] [PC:0x608D7FE5] [ADDR:0x0] [UNABLE_TO_READ] []
数据库启动失败,级别太低,转储文件看不懂。
此时数据库由于有冷备份,所以直接从冷备份里恢复。否则,就只能介质恢复,然后使用日志文件前滚,再在适当的时候resetlogs打开数据库。
真心搞不懂,ORACLE为什么不对这类表做保护,既然可以拦截ddl操作,那么完全可以拦截dml操作呀?!