收缩临时表空间
?? ???? 當排序操作、重建索引等大型操作無法在內存中完成時,臨時表空間將為排序提供便利。一般情況下臨時表空間為多個用戶,多個會話所共
享。不能為會話分批空間配額。臨時表空間耗用過度且在不能自動擴展的情形下將收到“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
享。不能為會話分批空間配額。臨時表空間耗用過度且在不能自動擴展的情形下將收到“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
總結
- 上一篇: 如何直接soap字符串,访问webser
- 下一篇: 产品经理面试必问问题与答题模板