数据库收缩数据文件的尝试(二)(r11笔记第9天)

在之前自己的一个测试环境中,因为本身磁盘空间不足,导致一个测试库数据目录溢出,最后花了点功夫,将一个2G左右的文件经过收缩的操作后,竟然收缩为7M。详情可以参考 收缩关于收缩数据文件的尝试(r5笔记第34天)

    而隔了很长一段时间后,我在线上一个环境碰到了类似的问题。

这个数据库是一个OLAP的业务库,之前的数据量还不小,大概有1.7T,但是经过业务梳理之后,有一部分业务不需要的数据就删除了,后续迁移了另外一个环境的数据过来。

    从资源的规划来看,这个库的数据增长还远远达不到目前的使用量,所以也不用考虑太多的扩容需求,但是问题来了,现在的库已经被撑大了。想要收缩就难了。当前的问题其实挺严峻,下面的磁盘分区已经超过了报警阈值。

/dev/sdb              1.7T  1.5T  127G  92% /U01

但是从DB层面来看,所能做的工作似乎很少。因为尝试resize操作,只能收缩很小的空间。

这里就涉及一个数据文件的“高水位线”问题,大体来说,就是数据文件很大,但是里面的数据分布情况是不均匀的。很可能出现较大的断层,这样一来数据空间使用不充分,但是物理空间却无法轻易释放。造成的一种比较尴尬的情况就是下面的样子。剩余空间1.1T,使用空间才300多G,空间的使用率完全没有合理释放出来。

Tablespace           STA M A Init     Total MB    Free MB     Used MB
-------------------- --- - - ---- ------------ ---------- -----------
AUDIT_TAB            OLN L S  64K            3          1           2
CMBI_MIN_DATA        OLN L S  64K    1,183,573    847,492     336,081
CMBI_MIN_INDEX       OLN L S  64K      269,454    221,167      48,287
SYSAUX               OLN L S  64K          870         68         802
SYSTEM               OLN L S  64K          700        374         326
TEMP                 OLN L U   1M       63,487     63,487           0
UNDOTBS1             OLN L S  64K       38,304     26,206      12,098
USERS                OLN L S  64K          204         11         193
                                  ------------ ---------- -----------
sum                                  1,556,594  1,158,805     397,790

所以这种情况需要改善,但是收起来容易,做起来难。

因为我很快发现问题比我想的要复杂一些。大体来说数据文件的高水线县问题有三类。

在数据文件的起始位置附近。

数据库收缩数据文件的尝试(二)(r11笔记第9天)

或者是中间的位置

在数据文件的中间出现较大的断层。

数据库收缩数据文件的尝试(二)(r11笔记第9天)
或者是末尾附近的位置。

数据库收缩数据文件的尝试(二)(r11笔记第9天)

总之,这些位置都有可能出现大量的碎片,使用脚本查看可以收缩的空间,竟然只能省出18M左右的空间。

     FILE#  CURRENTMB   RESIZETO  RELEASEMB RESIZECMD
---------- ---------- ---------- ---------- --------------------------------------------------------------------------------
        37 32767.9844 32748.9922 18.9921875 alter database datafile '/U01/app/oracle/oradata/tlbb3dbidb/cmbi_min_data21.dbf' resize 32749M;

所以这问题还是蛮纠结的。查看数据文件的高水线,对应的脚本如下:

sqlplus -s / as sysdba <<EOF
set linesize 200
col segment_name format a35
col segment_type format a15
col tablespace_name format a20
col file_name format a60
col partition_name format a20
set pages 50
select tablespace_name,file_name,bytes/1024/1024 size_MB from dba_data_files where file_id=$1;
select * from (select file_id,segment_name,partition_name,segment_type,max(block_id+blocks-1) HWM,block_id
             from dba_extents
             where file_id=$1
             group by file_id,block_id, segment_name,partition_name,segment_type order by hwm ) where rownum <decode('$2',null,5000,'$2');

col name format a30
col ResizeCMD format a80
set pages 100
select a.file#,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
          group by file_id) b
  where a.file# = b.file_id(+)
   and a.file#=$1
   and (a.bytes - HWM *block_size)>0 order by ReleaseMB;
EOF 只需要输入数据文件的id即可。

怎么尽可能全面,快捷的降低高水位线呢,一种方式就是在当前的数据文件中寻找那些空间使用出入较大的对象。

还有一种思路也算比较简单,就是新建一个表空间,然后把数据都迁移到这个表空间。

而通用的思路为了达到高可用性,可以使用在线重定义,或者是基于ROWID的方式来删除,插入数据,因为开启的事务级支持,所以依旧可以,而且操作起来也会有一些思路和方法可以参考。


上一篇:数据库文件过大如何收缩


下一篇:Jabba: hybrid error correction for long sequencing reads using maximal exact matches机译:Jabba:使用最大精