注册
删除数据后如何及时释放存储空间
专栏/金的探索记录/ 文章详情 /

删除数据后如何及时释放存储空间

2021/01/25 3219 4 1
摘要 删除数据后如何及时释放存储空间

当表空间大小受限时,即便通过 delete 带条件删除部分数据,被删除数据所使用的空间,依然不会被释放。此时想要再添加新的数据可能会得到“磁盘空间不足”的报错。

本文通过一个实验场景,介绍清理回滚段及时释放存储空间的方法,用以解决上述困扰。

创建实验场景步骤如下(注:本实验场景中数据页的大小 16 kB)

  1. 删除测试环境中的表和表空间(确保数据库中 TEST 表空间及 TEST_CLOB 表仅为本实验所用)。
drop table test_clob; drop tablespace test;
  1. 创建 test 表空间,大小为 64 MB,并且务必关闭表空间自动扩展功能。
create tablespace test datafile '/dm7/data/DAMENG1/test.dbf' size 64 autoextend off;
  1. 创建表
create table test_clob ( c1 int, c2 clob ) storage(on test,clusterbtr);
  1. 构建一个往 test_clob 表中增加大量数据匿名块
declare begin for i in 1..10000 loop insert into test_clob values(1, lpad('测试',32000,'空间限制')); commit; end loop; end; /

等待匿名块执行完成,会收到如下报错:

1.png

  1. 查看插入了多少条记录
select count(1) from test_clob;

2.png

  1. 删除 500 条记录
delete from test_clob where rowed <= 500; commit; 查询记录条数 select count(1) from test_clob;

3.png

再插入数据,看看是否报错?

4.png

truncate 好用,然而不能带条件删除,表空间大小本身又有局限,怎么才能将尚未释放的存储空间用起来?

解决方法

  1. 以 DBA 身份创建存储过程
create or replace procedure remove_space() as begin execute immediate ‘slter system set ‘’UNDO_RETENTION’’=1;’ dbms_lock.sleep(10); execute immediate ‘alter system set ‘’UNDO_RETENTION’’=900;’ end; /

以 DBA 身份调用上述存储过程。

call remove_space();
  1. 再插入 500 条试试,看是否报错?
declare begin for i in 1..500 loop insert into test_clob values(1, lpad(‘测试’,32000,’空间限制’)); commit; end loop; end; /

查一下总记录数。

select count(1) from test_clob;

5.png

问题解决。

原理描述

执行完第 6 步,添加数据时,依然收到“磁盘空间不足”的报错,因为这时候应用回滚段还未清理,磁盘空间并未释放。

未清理原因:由于需要根据回滚记录回溯、还原物理记录的历史版本信息,而不能在事务提交时立即清除当前事务产生的回滚记录。但是,如果不及时清理回滚段,可能造成回滚段空间的不断膨胀,占用大量磁盘空间。

DM 基于上述原因提供了自动清理、回收回滚段空间的机制。采取保留回滚段一段时间,然后自动清理回滚段空间的方式。这个保留回滚段的时间长度由 UNDO_RETENTION 参数指定,默认数值是 900,单位是秒。

这个参数是系统级动态参数,修改后即时生效,dm.ini 文件里可以查到它的值。

6.png

通过第 7 步,调整 UNDO_RETENTION 为 1 秒,并预留 10 秒给进程清理回滚段,之后将 UNDO_RETENTION 恢复为 900 秒。

以上便是关于如何通过调整 UNDO_RETENTION 参数值,迅速解决 delete 数据后不能及时释放表空间的问题的方法了。

评论
后发表回复

作者

文章

阅读量

获赞

扫一扫
联系客服