隨筆-314  評論-209  文章-0  trackbacks-0

          在數據庫的日常學習中,發現公司生產數據庫的默認臨時表空間temp使用情況達到了30G,使用率達到了100%;待調整為32G后,使用率還是為100%,導致磁盤空間使用緊張。根據臨時表空間的主要是對臨時數據進行排序和緩存臨時數據等特性,待重啟數據庫后,temp會自動釋放。于是想通過重啟數據庫的方式來緩解這種情況,但是重啟數據庫之后,發現臨時表空間temp的使用率還是100%,一點沒變。雖然運行中應用暫時沒有報什么錯誤,但是這在一定程度上存在一定的隱患,有待解決該問題。由于臨時表空間主要使用在以下幾種情況:
          1、order by or group by (disc sort占主要部分);
          2、索引的創建和重創建;
          3、distinct操作;
          4、union & intersect & minus sort-merge joins;

          5、Analyze 操作;
          6、有些異常也會引起TEMP的暴漲。

          Oracle臨時表空間暴漲的現象經過分析可能是以下幾個方面的原因造成的:
          1. 沒有為臨時表空間設置上限,而是允許無限增長。但是如果設置了一個上限,最后可能還是會面臨因為空間不夠而出錯的問題,臨時表空間設置太小會影響性能,臨時表空間過大同樣會影響性能,至于需要設置為多大需要仔細的測試。
          2.查詢的時候連表查詢中使用的表過多造成的。我們知道在連表查詢的時候,根據查詢的字段和表的個數會生成一個迪斯卡爾積,這個迪斯卡爾積的大小就是一次查詢需要的臨時空間的大小,如果查詢的字段過多和數據過大,那么就會消耗非常大的臨時表空間。
          3.對查詢的某些字段沒有建立索引。Oracle中,如果表沒有索引,那么會將所有的數據都復制到臨時表空間,而如果有索引的話,一般只是將索引的數據復制到臨時表空間中。
          針對以上的分析,對查詢的語句和索引進行了優化,情況得到緩解,但是需要進一步測試。
          總結:
          1.SQL語句是會影響到磁盤的消耗的,不當的語句會造成磁盤暴漲。
          2.對查詢語句需要仔細的規劃,不要想當然的去定義一個查詢語句,特別是在可以提供用戶自定義查詢的軟件中。
          3.仔細規劃表索引。如果臨時表空間是temporary的,空間不會釋放,只是在sort結束后被標記為free的,如果是permanent的,由SMON負責在sort結束后釋放,都不用去手工釋放的。查看有哪些用戶和SQL導致TEMP增長的兩個重要視圖:v$sort_usage和v$sort_segment。

          通過查詢相關的資料,發現解決方案有如下幾種:
          一、重建臨時表空間temp
          Temporary tablespace是不能直接drop默認的臨時表空間的,不過我們可以通過以下方法達到。
          查看目前的Temporary Tablespace
          SQL> select name from v$tempfile;

          NAME
          ———————————————————————
          D:\ORACLE\ORADATA\ORCL\TEMP01.DBF

          SQL> select username,temporary_tablespace from dba_users;
          USERNAME TEMPORARY_TABLESPACE
          ------------------------------ ------------------------------
          MGMT_VIEW TEMP
          SYS TEMP
          SYSTEM TEMP
          DBSNMP TEMP
          SYSMAN TEMP

          1.創建中轉臨時表空間
          create temporary tablespace TEMP1 TEMPFILE 'D:\ORACLE\ORADATA\ORCL\temp02.DBF' SIZE 512M REUSE AUTOEXTEND ON NEXT 1M

          MAXSIZE UNLIMITED;
          2.改變缺省臨時表空間 為剛剛創建的新臨時表空間temp1
          alter database default temporary tablespace temp1;
          3.刪除原來臨時表空間
          drop tablespace temp including contents and datafiles;
          4.重新創建臨時表空間
          create temporary tablespace TEMP TEMPFILE 'D:\ORACLE\ORADATA\ORCL\temp01.DBF' SIZE 512M REUSE AUTOEXTEND ON NEXT 1M MAXSIZE

          UNLIMITED;
          5.重置缺省臨時表空間為新建的temp表空間
          alter database default temporary tablespace temp;
          6.刪除中轉用臨時表空間
          drop tablespace temp1 including contents and datafiles;

          以上的方法只是暫時釋放了臨時表空間的磁盤占用空間,是治標但不是治本的方法,真正的治本的方法是找出數據庫中消耗資源比較大的sql語句,然后對其進行優化處理。下面是查詢在sort排序區使用的執行耗時的SQL:

          Select se.username,se.sid,su.extents,su.blocks*to_number(rtrim(p.value))as Space,tablespace,segtype,sql_text
          from v$sort_usage su,v$parameter p,v$session se,v$sql s
          where p.name='db_block_size' and su.session_addr=se.saddr and s.hash_value=su.sqlhash and s.address=su.sqladdr order by se.username,se.sid;
          或是:
          Select su.username,su.Extents,tablespace,segtype,sql_text
          From v$sort_usage su,v$sql s
          Where su.SQL_ID = s.SQL_ID;
          注:如果原臨時表空間無用戶使用(select tablespace_name,current_users,total_blocks,used_blocks,free_blocks,free_blocks/total_blocks from v$sort_segment;),如果是文件系統可以看看文件的時間戳。
          我們可以刪除該表空間:如果原臨時表空間還有用戶在使用,你是刪除不了這個表空間的!在一次生產環境的臨時表空間切換中,原臨時表空間始終有用戶在上面,即使我關閉了前臺程序,也還是有用戶,新的臨時表空間已經沒有用戶在使用了。我估計用戶進程已經死在原臨時表空間了,后來只有重新啟動數據庫才能把原來舊的臨時表空間給刪除。

          二、修改參數(這個方案緊適用于8i及8i以下的版本)
          修改一下TEMP表空間的storage參數,讓Smon進程觀注一下臨時段,從而達到清理和TEMP表空間的目的。
          SQL>alter tablespace temp increase 1;
          SQL>alter tablespace temp increase 0;

          三、Kill session
          1、 使用如下語句a查看一下認誰在用臨時段
          SELECT se.username, se.SID, se.serial#, se.sql_address, se.machine, se.program, su.TABLESPACE,su.segtype, su.CONTENTS FROM

          v$session se, v$sort_usage su WHERE se.saddr = su.session_addr
          2、kill正在使用臨時段的進程
          SQL>Alter system kill session 'sid,serial#';
          3、把TEMP表空間回縮一下
          SQL>Alter tablespace TEMP coalesce;

          注:這處方法只能針對字典管理表空間(Dictionary Managed Tablespace)。于本地管理表空間(LMT:Local Managed Tablespace),不需要整理的。9i以后只能創建本地管理的表空間。
          CREATE TABLESPACE TEST DATAFILE 'D:\TEST01.dbf' SIZE 5M EXTENT MANAGEMENT DICTIONARY
          CREATE TABLESPACE TEST DATAFILE 'D:\TEST01.dbf' SIZE 5M EXTENT MANAGEMENT LOCAL;

          四、使用診斷事件,也是相對有效的一種方法

          1、查詢事件代碼
          SQL>select ts#, name from sys.ts$ ;
          TS# NAME
          ---------- ------------------------------
          0 SYSTEM
          1 UNDOTBS1
          2 SYSAUX
          3 TEMP
          4 USERS
          5 UNDOTBS2
           2、 執行清理操作
           SQL>alter session set events 'immediate trace name DROP_SEGMENTS level 4';
          說明:temp表空間的TS# 為 3, So TS#+ 1= 4。

          oracle臨時表空間過大的原因
          2009-05-12 11:22
          Oracle臨時表空間主要是用來做查詢和存放一些緩存的數據的,磁盤消耗的一個主要原因是需要對查詢的結果進行排序,如果沒有猜錯的話,在磁盤空間的(內存)的分配上,Oracle使用的是貪心算法,如果上次磁盤空間消耗達到1GB,那么臨時表空間就是1GB,如果還有增長,那么依此類推,臨時表空間始終保持在一個最大的上限。Oracle臨時表空間暴漲的現象經過分析可能是以下幾個方面的原因造成的。
                  1. 沒有為臨時表空間設置上限,而是允許無限增長。但是如果設置了一個上限,最后可能還是會面臨因為空間不夠而出錯的問題,臨時表空間設置太小會影響性能,臨時表空間過大同樣會影響性能,至于需要設置為多大需要仔細的測試。
                  2.查詢的時候連表查詢中使用的表過多造成的。我們知道在連表查詢的時候,根據查詢的字段和表的個數會生成一個迪斯卡爾積,這個迪斯卡爾積的大小就是一次查詢需要的臨時空間的大小,如果查詢的字段過多和數據過大,那么就會消耗非常大的臨時表空間。
                 3.對查詢的某些字段沒有建立索引。Oracle中,如果表沒有索引,那么會將所有的數據都復制到臨時表空間,而如果有索引的話,一般只是將索引的數據復制到臨時表空間中。
                 針對以上的分析,對查詢的語句和索引進行了優化,情況得到緩解,但是需要進一步測試。

                 總結:
                 1.SQL語句是會影響到磁盤的消耗的,不當的語句會造成磁盤暴漲。
                 2.對查詢語句需要仔細的規劃,不要想當然的去定義一個查詢語句,特別是在可以提供用戶自定義查詢的軟件中。
                 3.仔細規劃表索引。

          如果臨時表空間是temporary的,空間不會釋放,只是在sort結束后被標記為free的,如果是permanent的,由SMON負責在sort結束后釋放,都不用去手工釋放的。查看有哪些用戶和SQL導致TEMP增長的兩個重要視圖:
          v$sort_usage和v$sort_segment
          對于非LMT管理方式的TEMP表空間,最簡單的方法是Metalink給出的一個方法:
          修改一下TEMP表空間的storage參數,讓Smon進程觀注一下臨時段,從而達到清理和TEMP表空間的目的。
          SQL>alter tablespace temp default storage(pctincrease 1);
          SQL>alter tablespace temp default storage(pctincrease 0);

          而對于LMT管理方式的TEMP表空間,需要重新建立一個新的臨時表空間,將所有用戶的默認臨時表空間指定到新的表空間上,然后offline舊的臨時表空間,并drop掉。具體步驟如下:
          首先查詢用戶的缺省臨時表空間:

          [oracle@jumper oracle]$ sqlplus "/ as sysdba"

          SQL*Plus: Release 9.2.0.4.0 - Production on Wed Apr 12 11:11:43 2006

          Copyright (c) 1982, 2002, Oracle Corporation. All rights reserved.


          Connected to:
          Oracle9i Enterprise Edition Release 9.2.0.4.0 - Production
          With the Partitioning option
          JServer Release 9.2.0.4.0 - Production

          SQL> select username,temporary_tablespace from dba_users;

          USERNAME                       TEMPORARY_TABLESPACE
          ------------------------------ ------------------------------
          SYS                                 TEMP2
          SYSTEM                         TEMP2
          OUTLN                           TEMP2
          EYGLE                            TEMP2
          CSMIG                            TEMP2
          TEST                               TEMP2
          REPADMIN                     TEMP2
          ......

          13 rows selected.

          SQL> select name from v$tempfile;

          NAME
          ---------------------------------------------------------------------
          /opt/oracle/oradata/conner/temp02.dbf
          /opt/oracle/oradata/conner/temp03.dbf
           

          重建新的臨時表空間并進行切換:

          SQL> create temporary tablespace temp tempfile '/opt/oracle/oradata/conner/temp1.dbf' size 10M;

          Tablespace created.

          SQL> alter tablespace temp add tempfile '/opt/oracle/oradata/conner/temp2.dbf' size 20M;

          Tablespace altered.

          SQL> alter database default temporary tablespace temp;

          Database altered.

          SQL> select username,temporary_tablespace from dba_users;

          USERNAME                       TEMPORARY_TABLESPACE
          ------------------------------ ------------------------------
          SYS                                 TEMP
          SYSTEM                         TEMP
          OUTLN                           TEMP
          EYGLE                            TEMP
          CSMIG                           TEMP
          TEST                               TEMP
          REPADMIN                     TEMP
          .......

          13 rows selected.
           

          如果原臨時表空間無用戶使用(select tablespace_name,current_users,total_blocks,used_blocks,free_blocks,free_blocks/total_blocks from v$sort_segment;),如果是文件系統可以看看文件的時間戳。

          我們可以刪除該表空間:(如果原臨時表空間還有用戶在用,你是刪除不了這個表空間的!在一次生產環境的臨時表空間切換中,原臨時表空間始終有用戶在上面,即使我關閉了前臺程序,也還是有用戶,新的臨時表空間已經沒有用戶在使用了。我估計用戶進程已經死在原臨時表空間了。后來只有重新啟動數據庫才能把原來舊的臨時表空間給刪除。)

          SQL> drop tablespace temp2;

          Tablespace dropped.

          SQL>
          SQL> select name from v$tempfile;

          NAME
          ---------------------------------------------------------------
          /opt/oracle/oradata/conner/temp1.dbf
          /opt/oracle/oradata/conner/temp2.dbf

          SQL> select file_name,tablespace_name,bytes/1024/1024 MB,autoextensible
          2 from dba_temp_files
          3 /

          FILE_NAME                              TABLESPACE_NAME              MB AUTOEXTENSIBLE
          -------------------------------------- -------------------- ---------- --------------
          /opt/oracle/oradata/conner/temp2.dbf   TEMP                         20 NO
          /opt/oracle/oradata/conner/temp1.dbf   TEMP                         10 NO
           

          drop tablespace temp including contents and datafiles; --將表空間的內容和數據文件一起刪除。

          下面是查詢在sort排序區使用的執行耗時的SQL:
          Select se.username,se.sid,su.extents,su.blocks*to_number(rtrim(p.value))as    Space,tablespace,segtype,sql_text
            from v$sort_usage su,v$parameter p,v$session se,v$sql s
            where p.name='db_block_size' and su.session_addr=se.saddr and s.hash_value=su.sqlhash and s.address=su.sqladdr
            order by se.username,se.sid

          或是:

          Select su.username,su.Extents,tablespace,segtype,sql_text
          From v$sort_usage su,v$sql s
          Where su.SQL_ID = s.SQL_ID
           

           

          本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/xiaozhang0731/archive/2010/05/05/5557856.aspx

          posted on 2010-08-04 17:13 xzc 閱讀(2911) 評論(2)  編輯  收藏 所屬分類: Oracle

          評論:
          # re: ORACLE 臨時表空間使用率過高的原因及解決方案 2010-08-04 19:26 | xzc
          當你想知道是哪條sql在占用temp表空間的時候,你可以這樣:

          SELECT a.username, a.sid, a.serial#, a.osuser, b.tablespace, b.blocks, c.sql_text
          FROM v$session a, v$tempseg_usage b, v$sqlarea c
          WHERE a.saddr = b.session_addr
          AND c.address= a.sql_address
          AND c.hash_value = a.sql_hash_value
          ORDER BY b.tablespace, b.blocks;

          我們都知道,9iR2/10gR2里除了v$tempseg_usage外,還有v$sort_usage。單從結構上來看,v$tempseg_usage和v$sort_usage沒有任何區別,也就是說,上述sql其實是可以替換成:

          SELECT a.username, a.sid, a.serial#, a.osuser, b.tablespace, b.blocks, c.sql_text
          FROM v$session a, v$sort_usage b, v$sqlarea c
          WHERE a.saddr = b.session_addr
          AND c.address= a.sql_address
          AND c.hash_value = a.sql_hash_value
          ORDER BY b.tablespace, b.blocks;
            回復  更多評論
            
          # re: ORACLE 臨時表空間使用率過高的原因及解決方案 2010-08-04 19:40 | xzc
          --臨時表空間會話分析
          select b.tablespace 表空間,
          round(b.blocks * 8 / 1024 / 1024, 2) || 'G' "占用臨時空間",
          b.segtype 段使用類型, --HASH表示HASH關聯 SORT表示排序 DATA表示數據
          a.sid,
          a.serial#,
          a.username 用戶名稱,
          a.logon_time 用戶登入時間,
          a.last_call_et "持續時間(秒)",
          a.machine 客戶端機器,
          a.program 客戶端工具,
          a.status 用戶會話狀態,
          c.sql_text 簡要SQL,
          c.sql_fulltext 完整SQL
          from v$session a, v$tempseg_usage b, v$sqlarea c
          where a.saddr = b.session_addr
          and c.address = a.sql_address
          and c.hash_value = a.sql_hash_value
          order by b.tablespace, b.blocks;  回復  更多評論
            
          <2010年8月>
          25262728293031
          1234567
          891011121314
          15161718192021
          22232425262728
          2930311234

          常用鏈接

          留言簿(12)

          隨筆分類

          隨筆檔案

          收藏夾

          搜索

          •  

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 德州市| 都匀市| 雷波县| 尼勒克县| 唐海县| 兴和县| 五家渠市| 华蓥市| 长岭县| 改则县| 清河县| 商水县| 如东县| 华安县| 丰顺县| 资源县| 乌拉特后旗| 博乐市| 阿尔山市| 新巴尔虎左旗| 珲春市| 绍兴县| 安徽省| 星座| 巨鹿县| 墨竹工卡县| 海淀区| 涪陵区| 安阳市| 平邑县| 湾仔区| 黄龙县| 集安市| 三河市| 孟津县| 深州市| 东海县| 阜南县| 余江县| 荔波县| 兴海县|