• 一次实验环境中的数据库空间整理经历


    最近在开发环境使用的服务器上,发现磁盘空间占满,主要是数据库文件占用的磁盘空间太大,F盘大小为100G,数据库文件就整整占用了99G,在该服务器上数据库文件有两个实例,一个为A占用了55G,一个为B占用了44G()。

    A实例:

    ****_INDX.DBF

    3G

    ****_DATA.DBF

    16.8G

    ****_DATA01.DBF

    16.8G

    t_INDX.DBF

    512M

    t_DATA.DBF

    1G

    PLAN_INDX01.DBF

    3.5G

    PLAN_DATA01.DBF

    1.7G

    B实例:

    A_INDX.DBF

    1G

    A_INDX02.DBF

    5G

    A_DATA.DBF

    16.8G

    A_DATA02.DBF

    28G

    SYSTEM01.DBF

    563M

    SYSAUX01.DBF

    550M

    UNDOTBS01.DBF

    5G

    TEMP01.DBF

    2.6G

    一.首先,是考虑缩减数据库空间

    1. 查找大表

    Sql语句:

    select t.owner,t.segment_name,segment_type,sum(bytes)/1024/1024/1024 o_size from dba_segments t
    where segment_type = 'TABLE'
    group by t.owner,t.segment_name,segment_type
    having sum(bytes)/1024/1024/1024 > 1

    查找分区表的条件是where segment_type = 'TABLE PARTITION'

    结果:

    A

    DATA_REPORT_LOG

    1.1298828125

    A

    TASKPROCESS_INFO

    1.494140625

    A

    FAULT_DATA

    1.099609375

    A

    EXCEED_DATA

    2.099609375

    ITEM_HIS

    10.099609375

     

    1. 实际查询EXCEED_DATA表中的记录为0,但是它占用的空间依然是2G,这是因为删除记录使用的是delete语句,delete语句是不释放表空间的,所以这里要使用truncate截短EXCEED_DATA记录,然后再强制释放表空间。

    Sql:

    TRUNCATE TABLE EXCEED_DATA

    alter table EXCEED_DATA enable row movement

    alter table EXCEED_DATA shrink space

     

    然后查询表空间使用情况

    Sql语句:

    SELECT a.tablespace_name "表空间名",

    total "表空间大小",

    free "表空间剩余大小",

    (total - free) "表空间使用大小",

    total / (1024 * 1024 * 1024) "表空间大小(G)",

    free / (1024 * 1024 * 1024) "表空间剩余大小(G)",

    (total - free) / (1024 * 1024 * 1024) "表空间使用大小(G)",

    round((total - free) / total, 4) * 100 "使用率 %"

    FROM (SELECT tablespace_name, SUM(bytes) free

    FROM dba_free_space

    GROUP BY tablespace_name) a,

    (SELECT tablespace_name, SUM(bytes) total

    FROM dba_data_files

    GROUP BY tablespace_name) b

    WHERE a.tablespace_name = b.tablespace_name

    结果:

    表空间名

    表空间大小(G)

    表空间剩余大小(G)

    表空间使用大小(G)

    使用率 %

    A_INDX

    5.9765625

    2.432617188

    3.543945313

    59.3

    QUEST_DATA

    0.09765625

    0.094726563

    0.002929688

    3

    SYSAUX

    0.52734375

    0.021850586

    0.505493164

    95.86

    USERS

    0.063476563

    0.001586914

    0.061889648

    97.5

    SYSTEM

    0.537109375

    0.006774902

    0.530334473

    98.74

    UNDOTBS3

    0.09765625

    0.095581055

    0.002075195

    2.13

    A_DATA

    42.7890625

    16.84375

    25.9453125

    60.64

    1. 然后考虑缩减A_DATA这个数据库文件,这里涉及一个HWM(高水位)的概念,需要查询表空间的最大block的位置

    参考如下资料:

    测试的时候向数据库中插入了大量的数据,测试完成后删除了测试用户以及其全部数据,但是数据文件却没有缩小。经查阅资料之后发现这是 Oracle “高水位”所致,那么怎么把这些数据文件的大小降下来呢?解决办法如下:

    概念:

    表空间的相关知识请见这里,详细的介绍了 Oracle 数据库的存储结构。

    高水位:High Water Mark (HWM),是段(Segment)的一个指标,界定了段(Segment)曾经配置过的 block 水位。

    据说,随着数据的 insert,所使用段(Segment)的数据块(data block)也不断增加,这时候高水位(HWM)也随着上升。当数据被删除后(无论是 delete 还是 truncate table)虽然被占用的数据块(data block)已经相应减少,但是高水位(HWM)并不会随之下降。当高水位(HWM)下存在大量的空白数据块(data block)时,如果发生全表扫描(Full Table Scan, FTS)就会造成很多额外的 IO。因为全表扫描(FTS)的时候读取段(Segment)中的数据块(data block)会一直读取到高水位(HWM)才结束。高水位(HWM)就是段(Segment)中数据块(data block)有没有使用的分界线,所以全表扫描(FTS)所花费的时间不但不会因为数据的删除而减少,反而会增加。(关于此段查询效率的内容有待验证,笔者未亲自验证。不过可以确定的是高水位确实不会随着数据的删除而下降。)

    降低高水位的正确做法是先降低HWM,再确定实际占有大小,再resize数据文件。

    数据文件比较多,我们用其中一个较大的文件做为 Demo,其它数据文件如法炮制即可。我选择的文件是:D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF 1.4GB 左右。

    1.登录 sqlplus:

    语法:sqlplus username/password@hostname:port/sid

    例:sqlplus system/orcl@localhost:1521/orcl

     

    2.查询这个数据文件的编号:

    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

     可以看到,我们要操作的数据文件的编号是4。

    2.根据文件 ID 查询这个数据文件最大数据块(data block)的编号:(似乎这个最大编号可以代表该数据文件中数据块的数量,这一点有待考证。)

    SQL> select max(block_id) from dba_extents where file_id=4;

    MAX(BLOCK_ID)
    -------------
    65673

    3.计算该表空间实际占用的空间:

    --查询数据块的大小,单位是 byte

    SQL> show parameter db_block_size;

    NAME TYPE VALUE
    ------------------------------------ ----------- ------------------------------
    db_block_size integer 8192

    --8192 byte = 8 kb

    --接下来计算该表空间占用的物理空间

    SQL> select 65673 * 8 / 1024 from dual;

    65673*8/1024
    ------------
    513.070313

    --实际占用的物理空间是 513MB 多点

    4.最后一步,把我们的数据文件尺寸修改得比这个表空间实际占用的物理空间大点就行了:

    SQL> alter database datafile 'D:\oracle\product\10.2.0\oradata\orcl\USERS01.DBF' resize 600m;

    数据库已更改。

    OK,数据文件从修改前的 1.4GB 变成了 600MB。对于其它的数据文件,大家也知道如何收缩了吧?

    按照资料上操作,发现最大的数据块的编号和数据库文件A_DATA.DBF几乎相同。原因可能是虽然我释放了10G的表空间,但是因为数据段不连续,最高水位的block编号依然没有减小。

    二.缩减回滚段表空间

    在操作上述步骤过程中,发现回滚段表空间几乎没有使用,而开发环境中目前也没有未提交的事务,但是回滚段表空间两个实例却分别占用了14G和5G的磁盘空间,所以考虑采用释放回滚段表空间的方法。

    1. 首先查看回滚段状态

    Sql语句:

    select *
      From dba_rollback_segs r, v$rollstat v
      Where r.segment_id = v.usn(+)
      order by segment_name;

    结果:

    SYSTEM     SYS   SYSTEM    ONLINE

    _SYSSMU12$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU13$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU14$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU15$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU16$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU17$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU18$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU19$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU20$     PUBLIC     UNDOTBS3       ONLINE

    _SYSSMU21$     PUBLIC     UNDOTBS3       ONLINE

    所有的回滚段都是online

    1. 新建回滚段文件,并将数据库的回滚段指向该文件

    create undo tablespace undotbs2 datafile

    ORALCE安装目录 + '\ORADATA\GGG\UNDOTBS02.DBF' size 100M;

    alter system set undo_tablespace = undotbs2 scope = both;

    1. 等待原回滚段offline
    2. 删除原回滚段表空间

    drop tablespace undotbs1 including contents;

    drop tablespace UNDOTBS1 INCLUDING CONTENTS and datafiles;

    但是回滚段文件在磁盘上依然不会删除

    1. 手动删除回滚段文件

    停止实例服务,手动删除

    在第一次的操作过程中,在查找到超过10G的大表后,我直接drop该表,但是实际上drop操作并没有真正释放表空间,而是将表移动到回收站中,后来我又闪回该表之后,再截短

    闪回sql:

    flashback table ITEM_HIS to before drop

  • 相关阅读:
    JSP动作元素你又知几多?
    一个简单的TCP/IP服务端客户端对话
    使用Graphics2D去除曲线锯齿状
    MySQL数据类型
    Eclipse常用快捷键
    C#中的委托和事件
    GitHub当道,菜鸟也为Git疯狂
    C++文件操作
    JSP指令你知多少?
    spring如何使用多个xml配置文件
  • 原文地址:https://www.cnblogs.com/bayu/p/6408718.html
Copyright © 2020-2023  润新知