8.1.2.138版本已支持对表空间文件进行收缩(包括系统表空间roll\temp\system\main和用户表空间文件),前提是表空间文件尾部簇未被分配使用的空间才能回收,文件中间的空洞是无法回收的。
语法:alter tablespace 表空间名 resize datafile ‘数据库文件路径’ to 收缩到的大小;
之前版本表空间文件只能放大不能缩小,临时表空间可通过系统过程收缩(sp_trunc_ts_file),且有一定风险,后续版本已废弃。
背景:适合当表空间预分配失误分配过大,可进行纠错,将表空间文件进行收缩;
磁盘空间有限,针对大表删除数据后需要回收空间以给其它表空间使用的场景;
方法:138版本已支持对表空间文件进行收缩(包括系统表空间roll\temp\system\main和用户表空间文件),前提是表空间文件簇未被分配使用的空间才能回收,或者表进行truncate或者drop后释放的空间才可以进行回收;
无法做到oracle的delete数据后对表使用空间进行shrink space语法进行空间的回收,可以对表进行表空间移动后,再收缩表空间文件,然后再移回的方式间接实现oracle的shrink space的功能,具体过程参见“实验过程”章节
风险:表所在表空间迁移,实际底层是对数据进行dml操作(trxid和rowid都会变),会产生大量的日志和回滚操作,对系统影响较大且风险高,尽量在闲时或者停应用情况下进行此类操作
语法:alter tablespace 表空间名 resize datafile ‘数据库文件路径’ to 收缩到的大小;
说明:如果收缩大小小于自身文件实际使用大小,会自动收缩到实际使用大小,如果文件无法收缩至收缩大小,此语法有时会报“无法回收簇”,有时也不会报错或提示,所以执行完后需要核实下文件是否真正收缩。在表空间文件下数据表都移走后,收缩文件,偶尔还是会报“无法回收簇”,手动checkpoint(100)后有时能成功,有时报错,需要等待一会(当系统自动根据刷检查点间隔时间进行刷新后generate by ckpt_interval)再执行即可成功
表空间回收是异步操作,普通表空间需要超过undo_retention后才会开始异步释放,可将undo_retation放小后,加快释放
该功能相对稳定的版本在8.1.2.172之后
怎么找出需要释放空间的表对象?【以下sql执行完 commit一下,某些版本会阻塞一些ddl操作】
–根据段(对象)进行分组,查看哪些对象分配的簇号较多,而实际使用空间并不多的段对象
select table_used_space(a.owner, a.segment_name)*page/1024.0/1024.0 as 对象实际使用空间_MB,count(0)as 分配的簇个数,a.owner, a.segment_name,a.segment_type,a.tablespace_name,max(extent_id)
from
dba_extents a,
dba_data_files b
where a.tablespace_name =b.tablespace_name and a.FILE_ID =b.FILE_ID
and b.tablespace_name=‘TTT’–表空间
and a.segment_type=‘TABLE’ --段对象类型
group by a.owner,a.segment_name,a.segment_type,a.tablespace_name
order by 2 desc,1 asc;
1、建测试表空间、测试表
–建测试表空间
create tablespace ttt datafile ‘/dm8/dmdbms138/DBTEST/ttt.dbf’ size 512 autoextend on next 5 maxsize 3000;
–建测试表及新增测试数据
create table test123(tid number primary key) tablespace ttt;
insert into test123 select level from dual connect by level <= 5000000;
commit;
2、查看表空间文件,包含对象,簇分配情况
select *
from
dba_extents a,
dba_data_files b
where
a.tablespace_name =b.tablespace_name
and a.FILE_ID =b.FILE_ID
and b.tablespace_name=‘TTT’;
3、测试删除表大部分数据后,收缩表空间文件到80M,失败,报错“无法回收的簇”
–测试删除大部分数据后收缩表空间文件到80M
delete from test123 where tid between 10000 and 4999999;
commit;
–收缩表空间文件到80M
alter tablespace “TTT” resize datafile ‘ttt.dbf’ to 80;
4、将表空间对象移到其它表空间(创建一个临时表空间文件做中转) 再移回后,收缩表空间文件成功,通过步骤2复查簇分配情况已变化
–新建临时中转表空间文件
create tablespace dm_test_mid datafile ‘/dm8/dmdbms138/DBTEST/dm_test_mid.dbf’ size 512;
–移到临时表空间
alter table test123 MOVE tablespace dm_test_mid;
–移回原来表空间
alter table test123 MOVE tablespace ttt;
–收缩原来表空间文件大小到80M
alter tablespace “TTT” resize datafile ‘ttt.dbf’ to 80;
–删除临时中转表空间文件
drop tablespace DM_TEST_MID;
查看空簇的seg_id 如果有非0的 都无法释放,如果都是0才可以释放空间
–查看表空间下各种簇【半满,全满,空闲,未分配】的数量 ,只有当state=FREE 并且seg_id都是=0时,这些簇才可以通过收缩文件大小进行释放
select ts_id,file_id,seg_id,state,count(0)as num
from vextents
where
--state='FREE' and
ts_id=6 --表空间id
group by ts_id,file_id,seg_id,state
order by ts_id,seg_id;
--查看段对象使用的各种簇情况
select
(select name from sysobjects where id=a.obj_id) as index_name,
(select bb.name from sysobjects aa join sysobjects bb on aa.PID=bb.id where aa.id=a.obj_id) as table_name,
N_FULL_EXTENT as 满簇个数,N_FREE_EXTENT 空闲簇个数 ,N_FRAG_EXTENT 半满簇个数
from VSEGMENT_INFOS a
where ts_id=6 --表空间id
–and n_free_Extent<>0
order by ts_id,seg_id;
8.1.2.192版本,可以对ROLL回滚表空间文件进行收缩,但是需要重启服务才可用,否则报“[-4598]:无法回收簇”
8.1.2.138之前使用系统过程收缩:
CALL SP_TRUNC_TS_FILE (表空间id, 文件id, 收缩目标大小);
CALL SP_TRUNC_TS_FILE (3, 0, 2048);
8.1.2.138之后使用通过表空间文件收缩:
Alter tablespace ***** resize ‘******’ ****;
我这在172版本也就是2022的10月度版测临时表空间 可以使用alter tablespace resize进行收缩 与138版本(2022的7月月度版本)中间间隔了164版本(2022的9月月度版本) ,根据月度版本的说明 期间只增加了动态视图 vextents/dba_extents 查询功能优化,修复“表空间上有事务未提交”的错误,所以猜测8.1.2.138版本应该就具备对用户表空间、临时表空间、roll表空间的收缩功能 但是在使用vextents/dba_extents时要注意下 尽量还是使用8.1.2.172的版本
call SP_TABLE_LOB_RECLAIM(‘SYSDBA’,‘T1’);
文章
阅读量
获赞
