segment header corruption的处理

1 表空间留用数据快为0-12711g,10g 0-7
2 段空间管理为对象段本身的前几个数据块,不够用在分。
1 系统分配与固定分配extent
1.1 性能问题
1 对于系统级别分配区的情况,在空间利用率上面有很大的提升,而对固定大小的分配区情况,使用固定较大的区可以增加大表的全表扫描的性能,连续IO较大。
1.2 表空间级碎片问题:
1 在统一区大小的表空间中,因为分配的extent大小一致,不会出现碎片问题,而在系统管理的区中,如果需要1M 或者8M大小的区时,那些64KB的区可能成为碎片,
2 ASSM段管理
2.1 OBJECT_ID与DATA_OBJECT_ID
OBJECT_ID为表ID,DATA_OBJECT_ID为段ID,其中表id是永远不会变的,而段id是会变化的,比如对表进行truncate操作
SELECT OBJECT_ID,OBJECT_NAME,DATA_OBJECT_ID  FROM DBA_OBJECTS WHERE OBJECT_NAME='DUMP01';
TRUNCATE TABLE DUMP01;
INSERT INTO DUMP01 SELECT * FROM DUMP02
其中DUMP01的DATA_OBJECT_iD由 73204变成73206
alter session set container=prodpdb1;
create table dump01 tablespace users as select * from dba_objects;
create table dump02 tablespace users as select * from dba_objects;
select * from dba_extents where segment_name like '%DUMP%' order by extent_id
 
alter system dump datafile 12 block min 1664 block max 1664;
2.2 三层位图
ORACLE插入数据搜寻数据块原理 HW
依次查询L3 – L2 – L1,最终定位到合适的DBA,处理L2/L1时需要PID哈希值;
1 L2-L1
根据段头L2 Hint for inserts定位L2,进程依据其PID哈希值定位L1 并根据L1.free判断是否有足够空间;
若满足条件跳转到该L1 BMB,否则尝试下一个L2 BMB;
2 L1-DBA
搜索L1 BMB,以进程pid哈希值作为start dba;
发现候选DBA时 进程以nowait模式尝试获取块,若此时块上有active进程则尝试下一个,5次尝试均失败后则释放L1 BMB进行buffer busy wait等待;
碰到unformatted块则一次性格式化N个块并更新HWM;
  
结论:
L3包含多个L2,L2包含多个L1,L1包含多个数据块。
在L3中选择L2,依赖L2 Hint for inserts。
在L2中选择L1,根据进程PID号的HASH值
在L1中选择数据块,也是根据进程PID号的HASH值。
若L2 BMB包含N个L1 ,L1 BMB又包含M个DBA,则理论上可支持N*M个并发插入进程;
但并未考虑到高水位线,进程只能访问HHWM之下的块,假如当前高水位线位于第M个块,则最大支持M个并发插入进程;
高水位线一次提升的块数= min(L1 BMB ranges, extent);
查找数据字典(就是dba_segments数据字典基表),确认段头位置。
在段头L3中找到第一个L2块位置。
到L2块中根据插入进程的pid号,做hash运算,得到一个随机数M,在L2中找到第M个L1块的位置信息。
在确定的L1块中,根据pid号继续做hash运算,得到一个随机数N,在L1中找到N号数据块,像N号数据块中插入数据。
2.2.1 经典案例HW低,导致insert产生buffer busy waits
Vage有一个很经典的调优案例;
2.2.1.1 症状
某ASSM表每天1分区,采用uniform extent每个1M;上午9:00开始并发插入,大约100多个进程;
每天9点左右开始出现buffer busy wait等待,十几分钟左右等待消失,然后压力高的时候,偶而出现竞争,但不如早高峰严重


分析:
通过试验发现新创建的表即便有两个L1 BMB, 可并发进程只选择其中1个,每个L1 BMB描述64个块;
这是由于高水位线的缘故,首次插入时 HHWM提升64个块,另1个L1 BMB描述的块均在HHWM之上故无法使用,此时并发度为64;
而当段大于64时,1个L1 BMB描述256个数据块,而高水位线以128块(extent)为单位增长,此时最高支持128个并发进程;
故过一段时间后症状消失,但偶尔会出现竞争; 
2.2.1.2 解决方案
作者采用两种措施
1 小于64M时,高水位线一次抬升64个块(受限于L1 BMB),人为提升高水位线到64M,理论上此时并发进程可插入到<64M的任何1个块中,并发度非常高;
2 大于64M时,高水位线一次抬升128个块(受限于extent size),故将其从1M改为4M(2M应该就可以了); 
目的都是为了提升插入并发度,其实还有1种解决方案,假定能估算每天数据量,可直接将高水位线提升至此;








段头的一些信息都存放在块9-11中我们可以dump看下具体的信息
SQL> alter system dump datafile 7 block min 9 block max 11;
System altered.
SQL> oradebug setmypid
Statement processed.
SQL> oradebug tracefile_name   
/u01/app/oracle/admin/orcl/udump/orcl_ora_13403.trc


select header_file, header_block, bytes, blocks, extents from dba_segments where segment_name='DUMP01';
 header_file :ID of the file containing the segment header(数据文件的编号)
header_block:ID of the block containing the segment header(存放段头的块编号)
SQL> col segment_name format a15
SQL> select segment_name, extent_id, block_id,  blocks, bytes from dba_extents where segment_name='TAB_DUMPTEST';


SEGMENT_NAME     EXTENT_ID   BLOCK_ID     BLOCKS      BYTES
--------------- ---------- ---------- ---------- ----------
TAB_DUMPTEST             0          9          8      65536
TAB_DUMPTEST             1         17          8      65536
TAB_DUMPTEST             2         25          8      65536
TAB_DUMPTEST             3         33          8      65536
TAB_DUMPTEST             4         41          8      65536
TAB_DUMPTEST             5         49          8      65536
TAB_DUMPTEST             6         57          8      65536
TAB_DUMPTEST             7         65          8      65536
TAB_DUMPTEST             8         73          8      65536
TAB_DUMPTEST             9         81          8      65536
TAB_DUMPTEST            10         89          8      65536
TAB_DUMPTEST            11         97          8      65536
TAB_DUMPTEST            12        105          8      65536
TAB_DUMPTEST            13        113          8      65536
TAB_DUMPTEST            14        121          8      65536
TAB_DUMPTEST            15        129          8      65536
TAB_DUMPTEST            16        137        128    1048576
TAB_DUMPTEST            17        265        128    1048576
TAB_DUMPTEST            18        393        128    1048576
TAB_DUMPTEST            19        521        128    1048576
TAB_DUMPTEST            20        649        128    1048576  
 ----从这个查询中我们可以看到现在该段有11个区与上面吻合


--查询数据行所在的file及block
select t.*,rowid,dbms_rowid.rowid_object(rowid) robject,
dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bno,
dbms_rowid.rowid_row_number(rowid) rno from dump01 t;
下面是我该表的一些信息
SQL> select rowid,dbms_rowid.rowid_object(rowid) robject,
  2  dbms_rowid.rowid_relative_fno(rowid) fno,dbms_rowid.rowid_block_number(rowid) bno,
  3  dbms_rowid.rowid_row_number(rowid) rno from TAB_DUMPTEST;
ROWID                 ROBJECT        FNO        BNO        RNO
------------------ ---------- ---------- ---------- ----------
AAANQEAAHAAAAGcAAC      54276          7        12          2
AAANQEAAHAAAAGcAAD      54276          7        12          3
AAANQEAAHAAAAGcAAE      54276          7        12          4


Start dump data blocks tsn(表空间编号): 15 file#(数据文件编号): 7 minblk 9 maxblk 11
buffer tsn: 15 rdba: 0x01c00009 (7/9)  RDBA(Tablespace relative database block address)是相对数据块地址,是数据字典(表空间及一些对象定义)所在块的地址 可以用 DBMS_UTILITY 包进行转化
SQL> SELECT DBMS_UTILITY.data_block_address_file (TO_NUMBER (LTRIM ('0x01c00009', '0x'), 'xxxxxxxx')) AS file_no,DBMS_UTILITY.data_block_address_block (TO_NUMBER (LTRIM ('0x01c00009', '0x'), 'xxxxxxxx')) AS block_no from dual;


   FILE_NO   BLOCK_NO
---------- ----------
         7          9    --7号数据文件第9个块
scn: 0x0000.0014d636 seq: 0x03 flg: 0x04 tail: 0xd6362003   --scn 数据块最后一次编辑记录的系统该编号 tail is used to keep track of consistency information between the beginning and end of the block against the possibility of distribution of oracle blocks over multiple OS blocks  frmt   is the block format which tells whether it’s Oracle 7 or Oracle 8 and higher block  chkval   which is checksum written to the blocks when it is set and used by Oracle in part to check the consistency and validity of the block   type  Type defines which type of block it is. In this example it is “Data Segment Header”
frmt: 0x02 chkval: 0x5227 type: 0x20=FIRST LEVEL BITMAP BLOCK    第一级位图块
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0CC2B400 to 0x0CC2D400
CC2B400 0000A220 01C00009 0014D636 04030000  [ .......6.......]
CC2B410 00005227 00000000 00000000 00000000  ['R..............]
CC2B420 00000000 00000000 00000000 00000000  [................]
        Repeat 1 times
CC2B440 00000000 00000000 00000000 00000004  [................]
CC2B450 FFFFFFFF 00000000 00000003 00000010  [................]
CC2B460 00010002 00000000 00000000 00000000  [................]
CC2B470 00000000 00000010 00000000 00000000  [................]
CC2B480 00000000 00000000 00000000 00000000  [................]
CC2B490 01C0000A 00000000 00000000 00000000  [................]
CC2B4A0 00000000 00000000 00000000 00000000  [................]
        Repeat 1 times
CC2B4C0 0000D404 00000000 00000000 01C00009  [................]
CC2B4D0 00000008 00000000 01C00011 00000008  [................]
CC2B4E0 00000008 00000000 00000000 00000000  [................]
CC2B4F0 00000000 00000000 00000000 00000000  [................]
        Repeat 8 times
CC2B580 00000000 00000000 00000000 11111111  [................]
CC2B590 11111111 00000000 00000000 00000000  [................]
CC2B5A0 00000000 00000000 00000000 00000000  [................]
        Repeat 484 times
CC2D3F0 00000000 00000000 00000000 D6362003  [............. 6.]
Dump of First Level Bitmap Block


--------------------------------
   nbits : 4 nranges: 2         parent dba(指绝对数据块地址):  0x01c0000a   poffset: 0     --表示block 9的parent block的地址,而这个block的地址正好是10#block的地址:rdba: 0x01c0000a。
   unformatted: 0       total: 16        first useful block: 3      
   owning instance : 1
   instance ownership changed at 
   Last successful Search 
   Freeness Status:  nf1 0      nf2 0      nf3 0      nf4 0      
   Extent Map Block Offset: 4294967295 
   First free datablock : 16     
   Bitmap block lock opcode 0
   Locker xid:     :  0x0000.000.00000000
   Inc #: 0 Objd: 54276 
  --------------------------------------------------------
  DBA Ranges :
  --------------------------------------------------------
   0x01c00009  Length: 8      Offset: 0      
   0x01c00011  Length: 8      Offset: 8      


   0:Metadata   1:Metadata   2:Metadata   3:FULL
   4:FULL   5:FULL   6:FULL   7:FULL
   8:FULL   9:FULL   10:FULL   11:FULL
   12:FULL   13:FULL   14:FULL   15:FULL     ---Metadata(元数据:数据仓库中非常重要的概念,管理数据的数据,oracle中的数据字典据都可以理解成元数据),其中0表示是block 9,1 表示block 10,2 表示block 11  其他显示的都是full,表示这些block上都已经没有可用的空闲空间  真正的数据是从12#block开始的
  --------------------------------------------------------
buffer tsn: 15 rdba: 0x01c0000a (7/10)
scn: 0x0000.0014d636 seq: 0x12 flg: 0x04 tail: 0xd6362112
frmt: 0x02 chkval: 0x5334 type: 0x21=SECOND LEVEL BITMAP BLOCK   第二级位图块
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0CC2B400 to 0x0CC2D400
CC2B400 0000A221 01C0000A 0014D636 04120000  [!.......6.......]
CC2B410 00005334 00000000 00000000 00000000  [4S..............]
CC2B420 00000000 00000000 00000000 00000000  [................]
        Repeat 1 times
CC2B440 00000000 00000000 00000000 01C0000B  [................]
CC2B450 00000012 00000001 00000011 00000000  [................]
CC2B460 00000000 00000000 0000D404 00000001  [................]
CC2B470 00000000 01C00009 00010001 01C00019  [................]
CC2B480 00010001 01C00029 00010001 01C00039  [....).......9...]
CC2B490 00010001 01C00049 00010001 01C00059  [....I.......Y...]
CC2B4A0 00010001 01C00069 00010001 01C00079  [....i.......y...]
CC2B4B0 00010001 01C00089 00010001 01C0008A  [................]
CC2B4C0 00010001 01C00109 00010001 01C0010A  [................]
CC2B4D0 00010001 01C00189 00010001 01C0018A  [................]
CC2B4E0 00010001 01C00209 00010001 01C0020A  [................]
CC2B4F0 00010001 01C00289 00010001 01C0028A  [................]
CC2B500 00010005 00000000 00000000 00000000  [................]
CC2B510 00000000 00000000 00000000 00000000  [................]
        Repeat 493 times
CC2D3F0 00000000 00000000 00000000 D6362112  [.............!6.]
Dump of Second Level Bitmap Block
   number: 18      nfree: 1       ffree: 17     pdba:     0x01c0000b 
   Inc #: 0 Objd: 54276
  opcode:0 
xid: 
  L1 Ranges :                     --L1 Ranges 中的哪些dba转为10进制如下:9 25 41 57 73 89 105 121 137 138 265 266 393 394 521 522 649 650每一个一级bitmap block管理多datablock
  --------------------------------------------------------
   0x01c00009  Free: 1 Inst: 1 
   0x01c00019  Free: 1 Inst: 1 
   0x01c00029  Free: 1 Inst: 1 
   0x01c00039  Free: 1 Inst: 1 
   0x01c00049  Free: 1 Inst: 1 
   0x01c00059  Free: 1 Inst: 1 
   0x01c00069  Free: 1 Inst: 1 
   0x01c00079  Free: 1 Inst: 1 
   0x01c00089  Free: 1 Inst: 1 
   0x01c0008a  Free: 1 Inst: 1 
   0x01c00109  Free: 1 Inst: 1 
   0x01c0010a  Free: 1 Inst: 1 
   0x01c00189  Free: 1 Inst: 1 
   0x01c0018a  Free: 1 Inst: 1 
   0x01c00209  Free: 1 Inst: 1 
   0x01c0020a  Free: 1 Inst: 1 
   0x01c00289  Free: 1 Inst: 1 
   0x01c0028a  Free: 5 Inst: 1 


  --------------------------------------------------------


buffer tsn: 15 rdba: 0x01c0000b (7/11)
scn: 0x0000.0014d639 seq: 0x01 flg: 0x04 tail: 0xd6392301
frmt: 0x02 chkval: 0x7e1d type: 0x23=PAGETABLE SEGMENT HEADER 这就是segment header block同时也是一个特殊的三级bitmap block
Hex dump of block: st=0, typ_found=1
Dump of memory from 0x0CC2B400 to 0x0CC2D400
CC2B400 0000A223 01C0000B 0014D639 04010000  [#.......9.......]
CC2B410 00007E1D 00000000 00000000 00000000  [.~..............]
CC2B420 00000000 00000015 00000300 00000A9C  [................]
CC2B430 00000014 00000044 00000080 01C002CD  [....D...........]
CC2B440 00000000 00000014 00000000 000002C4  [................]
CC2B450 00000000 00000000 00000000 00000014  [................]
CC2B460 00000044 00000080 01C002CD 00000000  [D...............]
CC2B470 00000014 00000000 000002C4 01C0028A  [................]
CC2B480 01C0028A 00000000 00000000 00000000  [................]
CC2B490 00000000 00000000 00000000 00000000  [................]
        Repeat 3 times
CC2B4D0 00000001 00002000 00000000 00001434  [..... ......4...]
CC2B4E0 00000000 01C0000A 00000001 01C0028A  [................]
CC2B4F0 01C0000A 00000000 00000000 00000000  [................]
CC2B500 00000000 00000000 00000015 00000000  [................]
CC2B510 0000D404 10000000 01C00009 00000008  [................]
CC2B520 01C00011 00000008 01C00019 00000008  [................]
CC2B530 01C00021 00000008 01C00029 00000008  [!.......).......]
CC2B540 01C00031 00000008 01C00039 00000008  [1.......9.......]
CC2B550 01C00041 00000008 01C00049 00000008  [A.......I.......]
CC2B560 01C00051 00000008 01C00059 00000008  [Q.......Y.......]
CC2B570 01C00061 00000008 01C00069 00000008  [a.......i.......]
CC2B580 01C00071 00000008 01C00079 00000008  [q.......y.......]
CC2B590 01C00081 00000008 01C00089 00000080  [................]
CC2B5A0 01C00109 00000080 01C00189 00000080  [................]
CC2B5B0 01C00209 00000080 01C00289 00000080  [................]
CC2B5C0 00000000 00000000 00000000 00000000  [................]
        Repeat 142 times
CC2BEB0 01C00009 01C0000C 01C00009 01C00011  [................]
CC2BEC0 01C00019 01C0001A 01C00019 01C00021  [............!...]
CC2BED0 01C00029 01C0002A 01C00029 01C00031  [)...*...)...1...]
CC2BEE0 01C00039 01C0003A 01C00039 01C00041  [9...:...9...A...]
CC2BEF0 01C00049 01C0004A 01C00049 01C00051  [I...J...I...Q...]
CC2BF00 01C00059 01C0005A 01C00059 01C00061  [Y...Z...Y...a...]
CC2BF10 01C00069 01C0006A 01C00069 01C00071  [i...j...i...q...]
CC2BF20 01C00079 01C0007A 01C00079 01C00081  [y...z...y.......]
CC2BF30 01C00089 01C0008B 01C00109 01C0010B  [................]
CC2BF40 01C00189 01C0018B 01C00209 01C0020B  [................]
CC2BF50 01C00289 01C0028B 00000000 00000000  [................]
CC2BF60 00000000 00000000 00000000 00000000  [................]
        Repeat 141 times
CC2C840 00000000 00000000 01C0000A 00000000  [................]
CC2C850 00000000 00000000 00000000 00000000  [................]
        Repeat 185 times
CC2D3F0 00000000 00000000 00000000 D6392301  [.............#9.]
  Extent Control Header
  -----------------------------------------------------------------
  Extent Header:: spare1: 0      spare2: 0      #extents: 21     #blocks: 768    
                  last map  0x00000000  #maps: 0      offset: 2716  
      Highwater::  0x01c002cd  ext#: 20     blk#: 68     ext size: 128    Highwater mark is at extent 20, block 68. This extent has 128 blocks. And there’re 708 data block below it.                                         ---128-68=60 data blocks free (低于hightwater mark)
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 708                                ---768-708=60 data blocks free (低于hightwater mark)       下面我查考了国外的论坛写了一个存过计算下空闲块存过的具体代码在文档的最后
SQL> set serveroutput on                          
SQL> exec show_space('TAB_DUMPTEST','SYS');
Total Blocks............................768
Total Bytes.............................6291456
Total MBytes............................6
Unused Blocks...........................60
Unused Bytes............................491520
Last Used Ext FileId....................7
Last Used Ext BlockId...................649
Last Used Block.........................68
PL/SQL procedure successfully completed.


  mapblk  0x00000000  offset: 20    
                   Unlocked
  --------------------------------------------------------A
  Low HighWater Mark : 
      Highwater::  0x01c002cd  ext#: 20     blk#: 68     ext size: 128   
  #blocks in seg. hdr's freelists: 0     
  #blocks below: 708   
  mapblk  0x00000000  offset: 20    
  Level 1 BMB for High HWM block: 0x01c0028a
  Level 1 BMB for Low HWM block: 0x01c0028a
  --------------------------------------------------------
  Segment Type: 1 nl2: 1      blksz: 8192   fbsz: 0      
  L2 Array start offset:  0x00001434
  First Level 3 BMB:  0x00000000
  L2 Hint for inserts:  0x01c0000a
  Last Level 1 BMB:  0x01c0028a
  Last Level II BMB:  0x01c0000a
  Last Level III BMB:  0x00000000
     Map Header:: next  0x00000000  #extents: 21   obj#: 54276  flag: 0x10000000       
                                                                                                        SQL> col name format a15  可以发现这就是我建立的表
                                                                                                        SQL> select obj#, owner#, name, status, ctime, type# from sys.obj$ where obj#=54276;
                                                                                                         OBJ#     OWNER# NAME                STATUS CTIME             TYPE#
                                                                                                               ---------- ---------- --------------- ---------- ------------ ----------
                                                                                                      54276          0 TAB_DUMPTEST             1 28-JAN-13             2
                                                                                                      这里的owner 0 表示sys用户的编号




  Inc # 0 
  Extent Map
  -----------------------------------------------------------------
   0x01c00009  length: 8     
   0x01c00011  length: 8     
   0x01c00019  length: 8     
   0x01c00021  length: 8     
   0x01c00029  length: 8     
   0x01c00031  length: 8     
   0x01c00039  length: 8     
   0x01c00041  length: 8     
   0x01c00049  length: 8     
   0x01c00051  length: 8     
   0x01c00059  length: 8     
   0x01c00061  length: 8     
   0x01c00069  length: 8     
   0x01c00071  length: 8     
   0x01c00079  length: 8     
   0x01c00081  length: 8     
   0x01c00089  length: 128   
   0x01c00109  length: 128   
   0x01c00189  length: 128   
   0x01c00209  length: 128   
   0x01c00289  length: 128   


  Auxillary Map
  --------------------------------------------------------
   Extent 0     :  L1 dba:  0x01c00009 Data dba:  0x01c0000c
   Extent 1     :  L1 dba:  0x01c00009 Data dba:  0x01c00011
   Extent 2     :  L1 dba:  0x01c00019 Data dba:  0x01c0001a
   Extent 3     :  L1 dba:  0x01c00019 Data dba:  0x01c00021
   Extent 4     :  L1 dba:  0x01c00029 Data dba:  0x01c0002a
   Extent 5     :  L1 dba:  0x01c00029 Data dba:  0x01c00031
   Extent 6     :  L1 dba:  0x01c00039 Data dba:  0x01c0003a
   Extent 7     :  L1 dba:  0x01c00039 Data dba:  0x01c00041
   Extent 8     :  L1 dba:  0x01c00049 Data dba:  0x01c0004a
   Extent 9     :  L1 dba:  0x01c00049 Data dba:  0x01c00051
   Extent 10    :  L1 dba:  0x01c00059 Data dba:  0x01c0005a
   Extent 11    :  L1 dba:  0x01c00059 Data dba:  0x01c00061
   Extent 12    :  L1 dba:  0x01c00069 Data dba:  0x01c0006a
   Extent 13    :  L1 dba:  0x01c00069 Data dba:  0x01c00071
   Extent 14    :  L1 dba:  0x01c00079 Data dba:  0x01c0007a
   Extent 15    :  L1 dba:  0x01c00079 Data dba:  0x01c00081
   Extent 16    :  L1 dba:  0x01c00089 Data dba:  0x01c0008b
   Extent 17    :  L1 dba:  0x01c00109 Data dba:  0x01c0010b
   Extent 18    :  L1 dba:  0x01c00189 Data dba:  0x01c0018b
   Extent 19    :  L1 dba:  0x01c00209 Data dba:  0x01c0020b
   Extent 20    :  L1 dba:  0x01c00289 Data dba:  0x01c0028b
  --------------------------------------------------------


   Second Level Bitmap block DBAs      --这里记录了二级位图块管理的地址
   --------------------------------------------------------
   DBA 1:   0x01c0000a   --也就是block 10


End dump data blocks tsn: 15 file#: 7 minblk 9 maxblk 11




存储过程具体代码
create or replace procedure show_space(p_segname   in varchar2,
                                       p_owner     in varchar2 default user,
                                       p_type      in varchar2 default 'TABLE',
                                       p_partition in varchar2 default NULL)
  authid current_user as
  l_free_blks          number;
  l_total_blocks       number;
  l_total_bytes        number;
  l_unused_blocks      number;
  l_unused_bytes       number;
  l_LastUsedExtFileId  number;
  l_LastUsedExtBlockId number;
  l_LAST_USED_BLOCK    number;




  procedure p(p_label in varchar2, p_num in number) is
  begin
    dbms_output.put_line(rpad(p_label, 40, '.') || p_num);
  end;




begin
  dbms_space.unused_space(segment_owner             => p_owner,
                          segment_name              => p_segname,
                          segment_type              => p_type,
                          partition_name            => p_partition,
                          total_blocks              => l_total_blocks,
                          total_bytes               => l_total_bytes,
                          unused_blocks             => l_unused_blocks,
                          unused_bytes              => l_unused_bytes,
                          LAST_USED_EXTENT_FILE_ID  => l_LastUsedExtFileId,
                          LAST_USED_EXTENT_BLOCK_ID => l_LastUsedExtBlockId,
                          LAST_USED_BLOCK           => l_LAST_USED_BLOCK);




  p('Total Blocks', l_total_blocks);
  p('Total Bytes', l_total_bytes);
  p('Total MBytes', trunc(l_total_bytes / 1024 / 1024));
  p('Unused Blocks', l_unused_blocks);
  p('Unused Bytes', l_unused_bytes);
  p('Last Used Ext FileId', l_LastUsedExtFileId);
  p('Last Used Ext BlockId', l_LastUsedExtBlockId);
  p('Last Used Block', l_LAST_USED_BLOCK);
end;
3 表区分配
 
从对数据段empxxxxx可以分析总结如下:
对于多数据文件表空间,数据段的extent被分配到不同的数据文件且不连续。
4 空间治理
1 由于表段的extent被分散分配到各个数据文件。Move对象段的方式进行数据文件回缩很鸡肋。
11.2以上建议truncate表时,直接将最后一个区,直接删除。
5 一篇好的测试文章


6 segment header corruption的处理
 
我们都知道,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。


部分内容转载:https://blogs.oracle.com/database4cn/segment-header-corruption%E7%9A%84%E5%A4%84%E7%90%86

猜你喜欢

转载自blog.csdn.net/oradbm/article/details/80689595