我们都知道,Oracle 从9iR2开始使用local managed tablespace来管理extent的分配情况,以替代原有用uet$/fet$表来管理的弊端,新特性是通过在
每个数据文件的file header block即block1后的1M的block中存放一个bitmap,每个bit代表一个extent,1 表示已经分配,0 表示未分配。
对于已经分配出去的extent,oracle都放在每个段内部进行自我管理,这个就是常说的ASSM,其中段的第一个extent的前三个block分别是一级块,二级块和三级块
我们称呼为L1,L2,L3,其中L3是最顶层管理块,有点类似索引的root block,L1是最底层块,类似索引的leaf block,直接管理datablock分配使用情况,L2是管理L1的使用情况,类似索引中的分支branch块,其中L3就是段头,segment header,那么一但这个segment header出现corruption会出现什么情况呢,如何处理呢?
下面我们来给您演示一下:
首先我们创建一个表
create table MAOB.MAOB_T tablespace user2 as select * from TABS
查看一下extent分配情况
select * from dba_extents where segment_name=’MAOB_T’ and owner=’MAOB’;
MAOB MAOB_T TABLE USER2 0 7 128 65536 8 7
分配了一个block id 176 起始的extents 查看segment header
select header_file,header_block from dba_SEGMENTS where segment_name=’MAOB_T’ and owner=’MAOB’;
7 130
segment header 是7,130
我们把segment header 弄成corruption,新shutdown db
SQL> shutdown immediate;
Database closed.
Database dismounted.
ORACLE instance shut down.
-bash-4.1$ echo CORRUPT | dd of=/refresh/oracle/oradata/orcl/users02.dbf bs=8192 conv=notrunc seek=130
0+1 records in
0+1 records out
8 bytes (8 B) copied, 0.000588696 s, 13.6 kB/s
再次启动db
SQL> startup
ORACLE instance started.
Total System Global Area 6413680640 bytes
Fixed Size 2265224 bytes
Variable Size 6358568824 bytes
Database Buffers 50331648 bytes
Redo Buffers 2514944 bytes
Database mounted.
Database opened.
SQL>
查看数据情况
select * from maob_t;
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 7, block # 130)
ORA-01110: data file 7: ‘/refresh/oracle/oradata/orcl/users02.dbf’
果然发现坏块了
查看extents分配情况
select * from dba_extents where segment_name=’MAOB_T’ and owner=’MAOB’;
no rows selected
发现已经没有extents情况了,说明segment 损坏之后会影响extents显示
再次查看free 空间情况
select * from dba_free_space where file_id=7
TABLESPACE_NAME FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
USER2 7 136 208601088 25464 7 <<free 起始blockid是136,正是第二个extent
drop 对象 看看发生什么
SQL> drop table maob.maob_t;
drop table maob.maob_t
*
ERROR at line 1:
ORA-01578: ORACLE data block corrupted (file # 7, block # 130)
ORA-01110: data file 7: ‘/refresh/oracle/oradata/orcl/users02.dbf’
仍然报错,说明这种情况已经不能处理这个对象了,这个时候若是有备份那么可以通过restore+recover来处理,
若是没有备份而且也不想恢复这个segment,只想释放出原有空间,那该如何处理呢?
首先需要 加purge 把表drop 掉,注意此处需要使用purge 语句,否则仍然会报错。
SQL> drop table maob_t purge;
Table dropped.
然后再次查看extent 是否释放
select * from dba_free_space where file_id=7
TABLESPACE_NAME FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
USER2 7 136 208601088 25464 7 <<free 起始blockid仍然是136说明并没有释放
继续对这个corruption segment执行如下步骤
exec dbms_space_admin.segment_corrupt(‘USER2’,7,130);
exec dbms_space_admin.segment_drop_corrupt(‘USER2’,7,130);
exec DBMS_SPACE_ADMIN.TABLESPACE_REBUILD_BITMAPS (‘USER2’);
然后再次查看extent 是否释放
select * from dba_free_space where file_id=7
TABLESPACE_NAME FILE_ID BLOCK_ID BYTES BLOCKS RELATIVE_FNO
USER2 7 128 208666624 25472 7 <<已经和前面的8个block合并在起了
至此,我们成功处理掉了segment header corruption的segment对象。
注:上述测试基于11204 database。