重庆思庄Oracle、Redhat认证学习论坛

标题: Resize Datafile时ORA-03297: 文件包含在请求的 RESIZE 值以外使用的数据 [打印本页]

作者: 郑全    时间: 2013-5-27 17:52
标题: Resize Datafile时ORA-03297: 文件包含在请求的 RESIZE 值以外使用的数据

前些天做测试,为了图方便,在sys用户下建立了一张大表,插入的数据大概几亿条,导致system空间增长了30G左右,后面想删除数据,缩小system空间,因此truncate table,后面又drop table,但是此时只是降低了段的高水位,数据文件还有高水位,因此磁盘空间并没有被释放。

1、先查询可以利用的空闲空间
SQL> select sum(bytes/1024/1024/1024) from dba_free_space where tablespace_name='SYSTEM';

SUM(BYTES/1024/1024/1024)
-------------------------
               31.4642944

 

2、计算datafile可以resize收缩的空间,也就是必须剩余部分其他对象正在使用的空间
    select a.file#,a.name,a.bytes/1024/1024 CurrentMB,  
       ceil(HWM * a.block_size)/1024/1024 ResizeTo,  
       (a.bytes - HWM * a.block_size)/1024/1024 ReleaseMB,  
       'alter database datafile '''||a.name||''' resize '||  
       ceil(HWM * a.block_size/1024/1024) || 'M;' ResizeCMD  
from v$datafile a,  
     (select file_id,max(block_id+blocks-1) HWM  
       from dba_extents where file_id in   
              (select b.file#  From v$tablespace a ,v$datafile b  
                where a.ts#=b.ts# and a.name='SYSTEM')
       group by file_id) b  
where a.file# = b.file_id(+)  
and (a.bytes - HWM *block_size)>0  
order by 5  
/


     FILE#
----------
NAME
----------------------------------------------------------------------------------------------
 CURRENTMB   RESIZETO  RELEASEMB
---------- ---------- ----------
RESIZECMD
----------------------------------------------------------------------------------------------
         1
D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSTEM01.DBF
      1024      545.5      478.5
alter database datafile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSTEM01.DBF' resize 546M;


3、直接收缩数据文件
SQL> ALTER DATABASE DATAFILE 'D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF' RESIZE 546m;
    正常情况下这样就可以了,但是我在计算datafile可以resize收缩的空间时,发现只能收缩至30G左右,如果收缩太小,出错
SQL> ALTER DATABASE DATAFILE 'D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF' RESIZE 10240M;
第 1 行出现错误:
ORA-03297: 文件包含在请求的 RESIZE 值以外使用的数据

    文件也有高水位,不是你想RESIZE到多少就多少的,有些有效数据被切掉,当然是不允许的,但是除了原来那张大表,剩余的数据不可能占用怎么大的空间,所以估计是哪个表或其他对象还占用了大量空间

 

4、找到文件对应的文件号
SQL> select file#,name from v$datafile;

     FILE# NAME
---------- --------------------------------------------------------------------------------
         1 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSTEM01.DBF
         2 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\UNDOTBS01.DBF
         3 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSAUX01.DBF
         4 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\USERS01.DBF
         5 D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\EXAMPLE01.DBF
         6 E:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\XTFDB\UNIEAP.DBF
         7 E:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\XTFDB\NEUDOC.DBF
         8 E:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\XTFDB\ELARP.DBF
         9 E:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\XTFDB\SEAS.DBF
        10 E:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\XTFDB\DLMIS.DBF

 

5、看下找到文件中最大的块号
SQL> select max(block_id) from dba_extents where file_id=1;
SQL> select owner,segment_name,segment_type,tablespace_name,extent_id from dba_extents where block_id=(select max(block_id) from dba_extents);
 owner  segment_name   segment_type tablespace_name extent_id  
------  -------------- ------------ --------------- ---------
 SYS    C_OBJ#_INTCOL#    CLUSTER     SYSTEM            18

 

6、主要是C_OBJ#_INTCOL#这个聚簇段占用的块的位置的太大了,接下来要先查出这个聚簇段属于某张表
SQL> select * from dba_clu_columns where cluster_name='C_OBJ#_INTCOL#';

OWNER                          CLUSTER_NAME                   CLU_COLUMN_NAME               TABLE_NAME                  TAB_COLUMN_NAME
------------------------------ ------------------------------ ------------------------------ --------------------------  ---------------
SYS                            C_OBJ#_INTCOL#                 OBJ#                          HISTGRM$                        OBJ#

SYS                            C_OBJ#_INTCOL#                 INTCOL#                       HISTGRM$                        INTCOL#

可以看出来,是属于HISTGRM$表,HISTGRM$系统表,这个表是记录各个业务表的数据分布情况的,网络上查到其基本可以删除

 

7、截断c_obj#_intcol#
SQL> truncate cluster c_obj#_intcol#;truncate cluster c_obj#_intcol#       
第 1 行出现错误:ORA-00701: 无法变更热启动数据库所需的对象

8、截断HISTGRM$表
SQL> truncate table HISTGRM$;
ORA-14512:不能对聚集对象进行操作
ORA-00701:无法改变热启动数据库所需的对象

 

9、使用move
SQL> ALTER TABLE HISTGRM$ MOVE;
第 1 行出现错误:
ORA-14512: 不能对聚簇对象进行操作
一样的错误

 

   上网查:CLUSTER C_OBJ#_INTCOL#增长导致数据库的SYSTEM 表空间被大量占用,因为这个CLUSTER是一个BOOTSTRAP$对象。由于是BOOTSTRAP$对象,所以无法TRUNCATE.由于这个对象是251>56,因此不是核心BOOTSTRAP$对象,所以我们用得上EVENT 38003了。大意是修改一下event级别,然后重新启动后即可。

10、设置EVENT参数,重启数据库
SQL> alter system set EVENT="38003 trace name context forever, level 10"   SCOPE=SPFILE;
系统已更改。
SQL> shutdown immediate;
数据库已经关闭。
已经卸载数据库。
ORACLE 例程已经关闭。

SQL> startup
ORACLE 例程已经启动。

Total System Global Area  612368384 bytes
Fixed Size                  1250428 bytes
Variable Size             100666244 bytes
Database Buffers          503316480 bytes
Redo Buffers                7135232 bytes
数据库装载完毕。
数据库已经打开。

 

11、重新截断cluster c_obj#_intcol#
SQL> truncate cluster c_obj#_intcol#;
簇已截断。

 

12、Resize datafile
SQL> alter database datafile 'D:\ORACLE\PRODUCT\10.2.0\ORADATA\ORCL\SYSTEM01.DBF' resize 548M;

数据库已更改。

 

13、测试,确保没有影响
SQL> exec DBMS_STATS.GATHER_TABLE_STATS(ownname=>'scott', tabname=>'emp', estimate_percent=>30, method_opt=>'for all indexed columns size skewonly',cascade=>true, degree=>2);
PL/SQL 过程已成功完成。

 

14、检查使用exp与expdp是否可以顺利导出数据
我的exp出现如下错误:
C:\Documents and Settings\Administrator>exp scott/tiger file=e:/ymhtest.dmp

EXP-00008: 遇到 ORACLE 错误 600
ORA-00600: 内部错误代码, 参数: [19004], [], [], [], [], [], [],
. . 正在导出表                           BONUS
EXP-00008: 遇到 ORACLE 错误 600
ORA-00600: 内部错误代码, 参数: [19004], [], [], [], [], [], [],
. . 正在导出表                          COMMIT
EXP-00008: 遇到 ORACLE 错误 600
ORA-00600: 内部错误代码, 参数: [19004], [], [], [], [], [], [],
. . 正在导出表                            DEPT
EXP-00008: 遇到 ORACLE 错误 600
ORA-00600: 内部错误代码, 参数: [19004], [], [], [], [], [], [],
. . 正在导出

我的expdp出现如下错误:
ORA-39002: 操作无效
ORA-39070: 无法打开日志文件。
ORA-29283: 文件操作无效
ORA-06512: 在 "SYS.UTL_FILE", line 475
ORA-29283: 文件操作无效

   试过很多办法,最终还是无法解决,我的是oracle10.2.0。1的,有人说要打补丁才行,没试过,最后只好还原数据库,所以,要尽量小心。
    注意:这是不被支持的方法,建议在生产库中不要轻易实施,如果要实施
1、备份数据库
2、最好操作后要对重要的表进行一次分析,可能影响系统中的一些SQL的执行计划。






欢迎光临 重庆思庄Oracle、Redhat认证学习论坛 (http://bbs.cqsztech.com/) Powered by Discuz! X3.2