临时段的cleanup引起的enq:TT–content等待事件处理过程

文章目录

  • 1.问题描叙
  • 2.查因过程
  • 3.根因
  • 4.处理过程
    • 4.1 Mark目标segment为CORRUPT
    • 4.2 Drop目标segment
    • 4.3 释放占用的空间

1.问题描叙

接到用户抱怨无法修改表架构:
临时段的cleanup引起的enq:TT–content等待事件处理过程_第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的数据文件,都是由"Header File ID.Header Block ID"格式组成的segment_name,而且segment_type是TEMPORARY,说明都是一些临时段
当听到术语 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

你可能感兴趣的:(Oracle,oracle)