收缩临时表空间

Oracle临时表空间管理
        当排序操作、重建索引等大型操作无法在内存中完成时,临时表空间将为排序提供便利。一般情况下临时表空间为多个用户,多个会话所共
享。不能为会话分批空间配额。临时表空间耗用过度且在不能自动扩展的情形下将收到“ORA-1652:unable to extend temp segment” 错误.下面
描述了过度扩展后如何释放临时表空间。

与之相关的内容参考:
        Oracle 表空间与数据文件
        临时表空间的管理与受损恢复
        Oracle 彻底 kill session

一、临时表空间何时释放
        检索数据的会话游标关闭时,占用的临时空间即被释放
        数据库关闭,重启(一般情况),会话 log off

二、释放过大的临时表空间

1、查看当前临时表空间的情况
SQL> select * from v$version where rownum<2;

BANNER
----------------------------------------------------------------
Oracle Database 10g Release 10.2.0.3.0 - 64bit Production
SQL> @temp_sort_segment 

+==================================================================================+
| Segment Name            : The segment name is a concatenation of the             |
|                           SEGMENT_FILE (File number of the first extent)         |
|                           and the                                                |
|                           SEGMENT_BLOCK (Block number of the first extent)       |
| Current Users           : Number of active users of the segment                  |
| Total Temp Segment Size : Total size of the temporary segment in MB              |
| Currently Used Bytes    : Bytes allocated to active sorts                        |
| Extent Hits             : Number of times an unused extent was found in the pool |
| Max Size                : Maximum number of MB ever used                         |
| Max Used Size           : Maximum number of MB used by all sorts                 |
| Max Sort Size           : Maximum number of MB used by an individual sort        |
| Free Requests           : Number of requests to deallocate                       |
+==================================================================================+
-->此时临时表空间go_temp中达到了32GB
    Tablespace  Segment Current Currently Pct.   Extent      Max Max Used Max Sort     Free
          Name     Name   Users   Used MB Used     Hits  Size MB  Size MB  Size MB Requests
-------------- -------- ------- --------- ---- -------- -------- -------- -------- --------
TEMP           SYS.0.0        4         4    2    1,864      217      217      217        0
GO_TEMP        SYS.0.0        0         0    0    1,305   32,766      367      367        0
**************          ------- ---------      -------- -------- -------- -------- --------
sum                           4         4         3,169   32,983      584      584        0

SQL> col tbsname format a15
SQL> select s.name tbsname,t.name,(t.bytes/1024/1024) mb,t.status 
  2  from v$tablespace s,v$tempfile t                             
  3  where s.ts# = t.ts#;                                         

TBSNAME         NAME                                                       MB STATUS
--------------- -------------------------------------------------- ---------- -------
TEMP            /u02/database/ORADB/temp/tempORADB.dbf                  235 ONLINE
GO_TEMP         /u02/database/ORADB/temp/ORADB_tempORADB.dbf          32767 ONLINE

SQL> @temp_usage2      -->此时temp已使用的为4MB,而GO_TEMP未使用

TABLESPACE             MB_TOTAL    MB_USED    MB_FREE
-------------------- ---------- ---------- ----------
GO_TEMP                 32767          0      32767
TEMP                      218          4        214

2、观察及分析临时表空间的耗用情况
SQL> select count(*) from big_table;    -->开启另一个session

  COUNT(*)
----------
   2000000

SQL> select * from big_table order by 2,3,4,5,7,8 desc;  -->对big_table 实施排序

SQL> alter index pk_stock_tbl_arc rebuild;      -->开启另一个session重建索引

SQL> @temp_sort_segment.sql           -->可以看到此时temp表空间耗用达到234MB,go_temp的耗用达到375MB

    Tablespace  Segment Current Currently Pct.   Extent      Max Max Used Max Sort     Free
          Name     Name   Users   Used MB Used     Hits  Size MB  Size MB  Size MB Requests
-------------- -------- ------- --------- ---- -------- -------- -------- -------- --------
TEMP           SYS.0.0        4       234    2    2,077      234      234      230        0
GO_TEMP        SYS.0.0        1       375    1    2,055   32,766      375      375        0
**************          ------- ---------      -------- -------- -------- -------- --------
sum                           5       609         4,132   33,000      609      605        0

SQL> @temp_sort_users.sql  -->获得当前排序的会话

   INST_ID SID_SERIAL Username   OSUSER          SPID         MODULE     PROGRAM       MB_USED TABLESPACE STATEMENTS
---------- ---------- ---------- --------------- ------------ ---------- ---------- ---------- ---------- ----------
         1 1064,9259  SCOTT      oracle          14456        SQL*Plus   oracle@SZD        234 TEMP                4
                                                                         B (TNS V1-
                                                                         V3)

         1 1073,5166  GO_ADMIN   oracle          2480         SQL*Plus   oracle@SZD        375 GO_TEMP           1
                                                                         B (TNS V1-
                                                                         V3)
3、使用resize,缩小临时表空间,如不能缩小,转到下一步
SQL> SELECT 'alter database tempfile ''' || a.name || ''' resize ' || b.siz || 'M;'  resize_command
  2  FROM v$tempfile a
  3        ,(SELECT ceil(tmsize.maxblk * bk.value / 1024 / 1024) siz
  4       FROM (SELECT nvl(MAX(segblk#), 128) maxblk
  5            FROM v$sort_usage) tmsize
  6             ,(SELECT VALUE
  7            FROM v$parameter
  8            WHERE NAME = 'db_block_size') bk) b;

RESIZE_COMMAND
----------------------------------------------------------------------------------------
alter database tempfile '/u02/database/ORADB/temp/ORADB_tempORADB.dbf' resize 106M;
alter database tempfile '/u02/database/ORADB/temp/tempORADB.dbf' resize 106M;

-->实际上此时占用32GB的临时数据文件已经缩小
alter database tempfile '/u02/database/ORADB/temp/ORADB_tempORADB.dbf' resize 106M;

Database altered.

-->为便于演示,此时假定TEMP为过大的临时表空间且不能释放
-->下面调整表明已使用空间超出了分配的空间
SQL> alter database tempfile '/u02/database/ORADB/temp/tempORADB.dbf' resize 106M;  
alter database tempfile '/u02/database/ORADB/temp/tempORADB.dbf' resize 106M
*
ERROR at line 1:
ORA-03297: file contains used data beyond requested RESIZE value

SQL> select count(*) from v$sort_usage where tablespace='TEMP';   -->当前有未释放的临时段

  COUNT(*)
----------
         4
         
/**************************************************/
/* Author: Robinson Cheng                         */
/* Blog:   http://blog.csdn.net/robinson_0612     */
/* MSN:    robinson_0612@hotmail.com              */
/* QQ:     645746311                              */
/**************************************************/    
     
4、新建一个中转临时表空间
SQL> create temporary tablespace temp2 tempfile '/u02/database/ORADB/temp/ORADB_temp02.dbf' 
  2  size 10m autoextend on;
  
Tablespace created.

-->如果此时过大的临时表空间为缺省的临时表空间,则必须将缺省的临时表空间设置为新的临时表空间之后
SQL> select property_name,property_value from database_properties
  2  where property_name like 'DEFAULT_TEMP_TABLESPACE';

PROPERTY_NAME                  PROPERTY_VALUE
------------------------------ --------------------
DEFAULT_TEMP_TABLESPACE        TEMP
  
SQL> alter database default temporary tablespace temp2;

Database altered.

5、转移用户到中转临时表空间
-->过大临时表空间上的那些用户需要迁移到新建的临时表空间
-->查询dba_users视图查询哪些用户位于过大的临时表空间之上
-->并使用下面的命令将其切换到新的临时表空间
alter user <username> temporary tablespace temp2; 

6.等到过大临时表空间上的没有临时段被使用,即已经全部释放即可删除过大的临时表空间

SQL> show user;    -->由于当前用户为scott,所以临时表空间未能释放
USER is "SCOTT"

SQL> conn / as sysdba   -->切换到sysdba
Connected.

SQL> @temp_usage2      -->临时段已经被释放

TABLESPACE             MB_TOTAL    MB_USED    MB_FREE
-------------------- ---------- ---------- ----------
GO_TEMP                   106          0        106
TEMP                      235          0        235

-->如果没有释放在可以kill session的情况下kill session.利用前面获得的sid,serial#来执行(前提是允许该情况发生).
alter system kill session '1064,9259'

7.删除过大的临时表空间

SQL> alter tablespace temp tempfile offline;   -->先将其脱机

Tablespace altered.

SQL> drop tablespace temp including contents and datafiles;   -->删除临时表空间及相应的文件

Tablespace dropped.

SQL> select s.name tbsname,t.name,(t.bytes/1024/1024) mb,t.status                    
  2  from v$tablespace s,v$tempfile t                                                
  3  where s.ts# = t.ts#;                                                            
                                                                                     
TBSNAME         NAME                                                       MB STATUS 
--------------- -------------------------------------------------- ---------- -------
GO_TEMP       /u02/database/ORADB/temp/ORADB_tempORADB.dbf           106 ONLINE 
TEMP2        /u02/database/ORADB/temp/ORADB_temp02.dbf                10 ONLINE 

-->也可以使用下面的命令来完成仅仅删除单个文件
ALTER DATABASE TEMPFILE '/u02/database/ORADB/temp/tempORADB.dbf' DROP INCLUDING DATAFILES; -->删除单个文件

7、根据需求可以创建原来的临时表空间并将切换出去用户切换到此临时表空间

三、总结
1、关注alert_<sid>.log文件中的ORA-1652错误并调查什么原因导致该错误。有些时候并不是由于当前的SQL 导致临时表空间不能扩展,很可能
        由于前一个SQL耗用了99%的临时表空间,而后一个SQL执行时即出现错误。对于此类情况应调查前一SQL并调整避免过多的磁盘排序。
2、如果基于空间压力应该关闭临时表空间的自动扩展。因此为临时表空间设定合理的大小就成了一个问题。个人的解决方案是首先检查ORA-1652
    其次是观察业务高峰期的峰值。如前面查询中的字段Max Size(: Maximum number of MB ever used)的值来预估。如果大师们有更好的建议
    不妨拍砖。
3、通过重启数据库,临时表空间所耗用的大小有时候并不能缩小。
4、在Oracle 11g之前一般是通过创建中转临时表空间来达到缩小的目的。不是很完美,因为有些时候临时段未释放导致不能删除临时表空间及
        数据文件。在11g可以直接使用下面的命令来完成:
        alter tablespace temp shrink space;
        alter tablespace temp shrink tempfile '<dir>' keep n <mb/kb>;
5、系统缺省的临时表空间不能被删除,因此如果系统缺省的临时表空间过大删除前应该新置一个系统缺省的临时表空间。
6、删除过大临时表空间前其上的用户应该先将其设定到中转临时表空间,重建后再将其置回原状态。
7、减少磁盘排序的首要任务调整SQL,如避免笛卡尔积,为表添加合理的索引等。其次要考虑PGA的值是否设定合理。

四、相关参考
        Oracle 表空间与数据文件
        临时表空间的管理与受损恢复
        Oracle 彻底 kill session
### Oracle 数据库中释放临时表空间的方法 在 Oracle 数据库中,临时表空间主要用于存储排序操作、索引创建以及大对象(LOB)处理等中间数据。如果临时表空间未被及时释放,可能会导致性能下降或错误发生。以下是几种常见的方法来解决临时表空间无法释放的问题。 #### 1. **查看临时表空间的使用情况** 为了更好地了解当前临时表空间的状态,可以运行以下查询命令: ```sql SELECT c.tablespace_name, c.bytes / 1024 / 1024 / 1024 AS total_bytes, (c.bytes - d.bytes_used) / 1024 / 1024 / 1024 AS free_bytes, d.bytes_used / 1024 / 1024 / 1024 AS used_bytes FROM ( SELECT tablespace_name, SUM(bytes) bytes FROM dba_temp_files GROUP BY tablespace_name ) c, ( SELECT tablespace_name, SUM(bytes_cached) bytes_used FROM v$temp_extent_pool GROUP BY tablespace_name ) d WHERE c.tablespace_name = d.tablespace_name; ``` 此查询可以帮助识别哪些临时表空间正在被大量占用[^3]。 --- #### 2. **调整会话状态以释放资源** 有时,某些长时间运行的操作可能仍然持有临时段而未释放。可以通过终止相关会话来强制释放这些资源。首先,找到占用临时表空间较多的会话: ```sql SELECT s.sid, s.serial#, p.spid, t.blocks * 8 / 1024 AS mb_used FROM v$sort_usage u, v$session s, v$process p, v$tempseg_usage t WHERE u.session_addr = s.saddr AND s.paddr = p.addr AND t.segfile# = u.segment_file# AND t.segblock# = u.segment_block#; ``` 一旦定位到具体的会话 ID 和序列号,可执行以下命令结束该会话: ```sql ALTER SYSTEM KILL SESSION 'sid,serial#'; ``` 这一步骤通常能够有效回收由异常会话持有的临时表空间[^2]。 --- #### 3. **收缩临时表空间** 如果发现临时文件已经膨胀过大,即使没有活跃进程占用也可以尝试通过 `shrink` 命令压缩其大小: ```sql ALTER TABLESPACE temp SHRINK SPACE KEEP 50M; ``` 这里的参数 `KEEP` 表示保留最小的空间量(单位为字节)。注意,只有当数据库支持在线重定义功能时才能成功应用此命令[^3]。 --- #### 4. **重新配置临时表空间设置** 对于那些频繁遭遇 ORA-01652 错误的情况,建议优化初始分配策略并启用自动扩展机制。例如新建一个更大的临时表空间作为替代方案: ```sql CREATE TEMPORARY TABLESPACE TEMP_NEW TEMPFILE '/path/to/new/temp01.dbf' SIZE 1G AUTOEXTEND ON NEXT 100M MAXSIZE UNLIMITED; -- 将默认临时表空间切换过去 ALTER DATABASE DEFAULT TEMPORARY TABLESPACE TEMP_NEW; -- 删除旧版临时表空间前需确认不再有任何依赖关系存在 DROP TABLESPACE TEMP INCLUDING CONTENTS AND DATAFILES; ``` 以上脚本展示了如何安全迁移至新的更大容量的临时表空间结构[^4]。 --- #### 总结 针对 Oracle临时表空间未能正常释放的现象,应先诊断具体原因再采取相应措施。无论是清理残留连接还是重建更优设计下的存储布局都能显著改善此类问题的发生概率。
评论 5
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

清风智语

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值