Oracle收縮暫存資料表空間

來源:互聯網
上載者:User

當排序操作、重建索引等大型操作無法在記憶體中完成時,暫存資料表空間將為排序提供便利。一般情況下暫存資料表空間為多個使用者,多個會話所共用。不能為會話分批空間配額。暫存資料表空間耗用過度且在不能自動擴充的情形下將收到“ORA-1652:unable to extend temp segment” 錯誤.下面描述了過度擴充後如何釋放暫存資料表空間。

與之相關的內容參考:

Oracle 資料表空間與資料檔案

Oracle 暫存資料表空間的管理與受損恢複

Oracle 徹底 kill session

一、暫存資料表空間何時釋放

檢索資料的會話遊標關閉時,佔用的臨時空間即被釋放

資料庫關閉,重啟(一般情況),會話 log off

二、釋放過大的暫存資料表空間

<span style="font-family: Verdana;">
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、根據需求可以建立原來的暫存資料表空間並將切換出去使用者切換到此暫存資料表空間</span>

三、總結

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的值是否設定合理。

 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.