當排序操作、重建索引等大型操作無法在記憶體中完成時,暫存資料表空間將為排序提供便利。一般情況下暫存資料表空間為多個使用者,多個會話所共用。不能為會話分批空間配額。暫存資料表空間耗用過度且在不能自動擴充的情形下將收到“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的值是否設定合理。