文章目录
- 1.问题描叙
- 2.查因过程
- 3.根因
- 4.处理过程
- 4.1 Mark目标segment为CORRUPT
- 4.2 Drop目标segment
- 4.3 释放占用的空间
1.问题描叙
接到用户抱怨无法修改表架构:
2.查因过程
查看当前DB活动:
Select sid,serial#,osuser,program,terminal,sql_id,blocking_session,event,p1raw,p1text,p1,p2text,p2text,p2,p3text,p3,seconds_in_wait,state
from v$session where wait_class<>'Idle'
output:
当下,DB内存在很多enq:TT–content等待事件,其中红框内是smon进程,它在等待什么呢,结合ID2的定义,猜想应该是在做空间回收
ID1/ ID2的含义如下:
id1是tablespace number,ID2表明执行中的操作类型。以下是操作类型对应代码;
0- 用以避免在drop tablespace和创建rollback segment之间发生死锁
1- 用以串行化在给定表空间上创建数据文件
2- 用以避免在TSPITR tablespace point in time recovery期间发生其他类型操作
4- 用以在创建tablespace时锁住该tablespace id
8- 用以避免在ALTER TABLESPACE期间发生死锁
16- 即16进制的0×10,用以同步 分配和回收盘区,allocation and deallocation of extents.
32+ 用在增加数据文件add datafile和创建表空间时,其中ID2为 32(十进制的)+相对文件号relative file number
先看看ID1的情况:
SELECT * FROM V$TABLESPACE WHERE TS#=15;
TS# NAME INC BIG FLA ENC
---------- ------------------------------ --- --- --- ---
15 CES_DATA YES NO YES
对应的tablespace是CES_DATA,在来看CES_DATA表空间的情况
SQL> SELECT FILE_NAME,FILE_ID,TABLESPACE_NAME,BYTES/1024/1024 SIZE_IN_MB,MAXBYTES/1024/1024 MAXBYTES_IN_MB,ONLINE_STATUS FROM DBA_DATA_FILES WHERE TABLESPACE_NAME='CES_DATA';
FILE_NAME FILE_ID TABLESPACE_NAME SIZE_IN_MB MAXBYTES_IN_MB ONLINE_
---------------------------------------- ---------- ------------------------------ ---------- -------------- -------
/u2/oradata/pcicvs01/CES_DATA09.dbf 12 CES_DATA 27600 32767.9844 ONLINE
/u5/oradata/pcicvs01/CES_DATA.dbf 17 CES_DATA OFFLINE
/u4/oradata/pcicvs01/CES_DATA.dbf 18 CES_DATA 10000 10000 ONLINE
/u5/oradata/pcicvs01/CES_DATA01.dbf 22 CES_DATA 10000 10000 ONLINE
/u5/oradata/pcicvs01/CES_DATA02.dbf 24 CES_DATA 10240 10240 ONLINE
/u5/oradata/pcicvs01/CES_DATA03.dbf 25 CES_DATA 10000 0 ONLINE
/u5/oradata/pcicvs01/CES_DATA04.dbf 26 CES_DATA 10000 0 ONLINE
/u5/oradata/pcicvs01/CES_DATA05.dbf 27 CES_DATA 10240 10240 ONLINE
/u5/oradata/pcicvs01/CES_DATA06.dbf 28 CES_DATA 32765.0625 32767.9844 ONLINE
/u5/oradata/pcicvs01/CES_DATA07.dbf 29 CES_DATA 32766.0625 32767.9844 ONLINE
/u5/oradata/pcicvs01/CES_DATA08.dbf 30 CES_DATA 8672 20480 ONLINE
FILE_NAME FILE_ID TABLESPACE_NAME SIZE_IN_MB MAXBYTES_IN_MB ONLINE_
---------------------------------------- ---------- ------------------------------ ---------- -------------- -------
/u2/oradata/pcicvs01/CES_DATA10.dbf 31 CES_DATA 100 32767.9844 ONLINE
/u3/oradata/pcicvs01/CES_DATA11.dbf 32 CES_DATA 100 32767.9844 ONLINE
/u3/oradata/pcicvs01/CES_DATA12.dbf 33 CES_DATA 100 32767.9844 ONLINE
/u4/oradata/pcicvs01/CES_DATA13.dbf 34 CES_DATA 100 32767.9844 ONLINE
不幸的是看到file_id 17的文件是offline的状态,难道是offline的文件导致smon进程无法正常回收空间? (由这是一台测试DB,不清楚谁offline了这个DB,也因为没有启用archivelog,也无法将它on起来)
带着这个疑问,我们继续看看file_id 17的文件都有什么?
SQL> SELECT segment_name, segment_type, header_file, relative_fno, header_block,
bytes/POWER(1024, 2) AS "SIZE_MB"
FROM dba_segments
WHERE relative_fno=17
SEGMENT_NAME SEGMENT_TYPE HEADER_FILE RELATIVE_FNO HEADER_BLOCK SIZE_MB
--------------------------------------------------------------------------------- ------------------ ----------- ------------ ------------ ----------
17.767907 TEMPORARY 17 17 767907 .0625
17.767915 TEMPORARY 17 17 767915 .125
17.767907 TEMPORARY 17 17 767907 .0625
17.767915 TEMPORARY 17 17 767915 .125
从输出来看,这个被offline的数据文件,都是由
当听到术语 TEMPORARY 时,可能会在临时表空间中的尋找相關的segment,例如当连接表或执行不适合内存的排序操作时。
但这样的segment也可能存在于永久表空间中。 当执行以下操作之一时,就会创建这样的段。
ALTER TABLE … MOVE
CREATE TABLE … AS SELECT
CREATE INDEX …
ALTER INDEX … REBUILD
在这些操作期间,会创建一个 TEMPORARY 段。 当操作意外终止时,这些段不会被清除。
3.根因
在这里,原因就很清楚了,有人意外offline了file_id为17的数据文件,导致文件内事先存在的临时段没有被清除,当用户视图修改段结构时,等待smon进程清除临时段后释放在tablespace上的lock
看一下oracle对TT锁的描叙:
SQL> select * from v$lock_type where type='TT';
TYPE NAME ID1_TAG ID2_TAG IS_ DESCRIPTION
-------------------- ------------------------------ ------------------------------ ------------------------------ --- ------------------------------------------------------------
TT Tablespace tablespace ID operation NO Serializes DDL operations on tablespaces
4.处理过程
4.1 Mark目标segment为CORRUPT
PL/SQL 包 DBMS_SPACE_ADMIN 用于手动清理 TEMPORARY 段。 在第一步中,需要将段17.767907 标记为CORRUPT。 结合RELATIVE_FNO的值。
BEGIN
DBMS_SPACE_ADMIN.SEGMENT_CORRUPT(
tablespace_name => 'CESUSER',
header_relative_file => 17,
header_block => 767907,
corrupt_option => DBMS_SPACE_ADMIN.SEGMENT_MARK_CORRUPT
);
END;
/
4.2 Drop目标segment
将段标记为损坏后,可以将其删除。
SQL> BEGIN
DBMS_SPACE_ADMIN.SEGMENT_DROP_CORRUPT(
tablespace_name => 'CES_DATA',
header_relative_file => 17,
header_block => 767907
);
END;
/
4.3 释放占用的空间
此时该段被删除,但其占用的空间在DBA_FREE_SPACE中不可见。
SQL> SELECT SUM(bytes)/POWER(1024,3) AS "FREE_SPACE"
FROM dba_free_space
WHERE tablespace_name = 'CES_DATA';
FREE_SPACE
----------
192.136215
最后,需要重建表空间的位图。
SQL> BEGIN
DBMS_SPACE_ADMIN.TABLESPACE_REBUILD_BITMAPS(
tablespace_name => 'USERS'
);
END;
/
现在,可用空间随着删除段的大小而增加。
SQL> SELECT SUM(bytes)/POWER(1024,3) AS "FREE_SPACE"
FROM dba_free_space
WHERE tablespace_name = 'CES_DATA';
FREE_SPACE
----------
250.273469